2014-12-14 3 views
11

AllocatorAware 컨테이너를 올바르게 작성하는 방법을 이해하려고합니다.propagate_on_container_move_assignment의 사용 예

제 생각에 propagate_on_container_move_assignment typedef는 컨테이너 자체가 이동 할당 될 때 특정 Allocator 유형을 복사해야하는지 여부를 나타냅니다. 나는이의 예를 찾을 수 없기 때문에

그래서, 그것에 내 자신의 자상은 다음과 같을 것이다

감안할 때 컨테이너 유형 Container, Allocator 유형 allocator_type 및 내부 allocator_type 데이터 멤버 m_alloc :

Container& operator = (Container&& other) 
{ 
    if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value) 
    { 
    m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
     other.m_alloc 
    ); 
    } 

    return *this; 
} 

이 정보가 맞습니까?

또 다른 혼란의 원인은 중첩 된 typedef propagate_on_container_move/copy_assignment이 구체적으로 지정에 대해 이야기하고 있다는 것입니다.하지만 생성자는 어떻습니까? AllocatorAware 컨테이너의 이동 생성자 또는 복사 생성자도 이 typedef를 확인해야합니까? 나는 대답은 여기 것 생각 ... 의미는, 나는 또한 작성해야 할 것 : 나는 libc++<vector> 헤더를 공부하는 것이 좋습니다

Container(Container&& other) 
{ 
     if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value) 
     { 
     m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
      other.m_alloc 
     ); 
     } 
} 

답변

15

. 당신은 std :: lib implementors들이 사용하는 불필요한 밑줄들 모두를 다뤄야 할 것이다. 하지만 libC++에는 검사를 위해 C++ 11 호환 구현이 있습니다.

이동 할당 연산자

컨테이너 이동 할당 연산자는 별도의 세 가지 가능성에 대처해야합니다

  1. propagate_on_container_move_assignment는 사실이다.
  2. propagate_on_container_move_assignment은 거짓이고 lhs와 rhs의 할당자는 동일합니다.
  3. propagate_on_container_move_assignment은 거짓이며 lhs 및 rhs의 할당자는 서로 다릅니다.

가능한 경우 이러한 세 가지 경우 간의 결정은 런타임이 아닌 컴파일 타임에 이루어져야합니다. 특히 propagate_on_container_move_assignment은 컴파일 타임 상수이기 때문에 컴파일 타임에 {1}과 {2, 3} 세트 중에서 선택해야합니다. 컴파일 타임 상수에 대한 컴파일 시간의 분기는 표시 할 때 if 문 대신에 tag dispatching으로 종종 수행됩니다.

이 중 어느 것도 select_on_container_copy_construction을 사용하면 안됩니다. 이 함수는 컨테이너 복사 생성자에 대해 입니다.

경우 1에서 lhs는 먼저 lhs의 할당자를 사용하여 할당 된 모든 메모리를 할당 해제해야합니다. 먼저 rhs 할당자가이 메모리를 나중에 할당 해제 할 수 없기 때문에이 작업을 먼저 수행해야합니다. 그런 다음 lhs 할당자는 rhs 할당 자에서 이동 할당됩니다 (다른 이동 할당과 마찬가지로). 그런 다음 메모리 소유권이 rhs 컨테이너에서 lhs 컨테이너로 전송됩니다.컨테이너의 디자인이 rhs 컨테이너가 리소스가없는 상태 (빈약 한 디자인 imho)로 남아있을 수 없다면 rhs 컨테이너의 이동 된 rhs 할당자가 새 리소스를 할당 할 수 있습니다.

propagate_on_container_move_assignment이 거짓 인 경우 할당 자 비교가 런타임 작업이므로 런타임에 사례 2와 3 중 하나를 선택해야합니다.

사례 2의 경우 을 제외하고는을 제외하고 할당 자 할당을 할당 할 수 있습니다. 그 단계를 건너 뜁니다.

경우 3에서는 rhs 컨테이너의 컨테이너 소유권을 lhs 컨테이너로 이전 할 수 없습니다. 당신이 할 수있는 유일한 방법 인 것처럼 : 알고리즘은 컴파일 시간에 선택되어 있기 때문에 경우 1, 컨테이너의 value_typeMoveAssignableMoveInsertable (MoveConstructible)이 이동 될 필요

assign(make_move_iterator(rhs.begin()), make_move_iterator(rhs.end())); 

하는 것으로 - 컨테이너를 지정하십시오. 하지만 사례 2에서 value_typeMoveAssignableMoveInsertable (MoveConstructible)이되어야합니다. 런타임에 2와 3 사이를 선택하기 때문에 절대 존재하지는 않습니다. 그리고 3은 value_type에서 이러한 작업을 수행하여 assign을 수행해야합니다.

이동 지정 연산자는 컨테이너에 구현하기가 가장 복잡한 특수 멤버입니다. 나머지는 훨씬 쉽게 :

이동 생성자

이동 생성자는 단지 구조에게 할당을 이동하고 우측에서 자원을 훔친다.

복사 생성자

는 복사 생성자는 select_on_container_copy_construction(rhs.m_alloc)로부터 할당을 가져온 다음 복사를 위해 자원을 할당하는 것을 사용한다. propagate_on_container_copy_assignment에 해당하는 경우

복사 대입 연산자

복사 할당 연산자가 먼저 확인해야합니다. 그렇다면 lhs와 rhs 할당자가 서로 동일하지 않은 경우 lhs는 할당자가 복사가 할당 된 후 나중에 수행 할 수 없으므로 먼저 모든 메모리를 할당 해제해야합니다. 다음으로 propagate_on_container_copy_assignment 인 경우 할당자가 할당되고 그렇지 않으면 할당자가 할당됩니다. 그런 다음 요소를 복사하십시오 :

assign(rhs.begin(), rhs.end()); 
+0

'propagate_on_move_assignment'가 참이지만 lhs와 rhs의 할당자는 같지 않은 경우는 어떻게됩니까? 만일'propagate_on_move_assignment'가 참이라면 먼저 allocators가 equal을 비교 하는지를 검사해서는 안되며 만약 equal되어 있다면 할당자를 이동 할당하기 전에 모든 메모리의 할당을 해제 할 필요가 없습니다. (이 방법으로 이미 할당 된 메모리를 다시 사용할 수 있습니다) – Siler

+0

rhs에서 lhs까지 모든 메모리의 소유권을 이전 할 수있는 컨테이너 디자인이라면 lhs의 메모리를 다시 사용할 필요가 없습니다. 그러나 모든 메모리를 전송할 수 없으면 rhs가 제공 할 수없는 경우와 할당자가 동일한 경우 lhs의 메모리를 다시 사용하면 편리합니다. 나의 편견은 컨테이너 디자인이 메모리의 100 %가 전송 될 수있을 때 가장 좋으며, rhs는 리소스가없는 상태로 남겨 둡니다. –