7

여기에 이동 생성자와 함께 대부분의 모든 클래스에 대한 이동 할당을 정의하는 아주 쉬운 방법 :destruct + move 구조를 통한 이동 할당이 안전합니까?

class Foo { 
public: 
    Foo(Foo&& foo);      // you still have to write this one 
    Foo& operator=(Foo&& foo) { 
    if (this != &foo) {    // avoid destructing the only copy 
     this->~Foo();     // call your own destructor 
     new (this) Foo(std::move(foo)); // call move constructor via placement new 
    } 
    return *this; 
    } 
    // ... 
}; 

가에서이 포인터 안전에 대한 새로운 배치 한 다음 자신의 소멸자를 호출의 순서가 표준 C++ (11) ?

+2

당신의 이동 생성자가'noexcept'가되어야합니다. 그렇지 않으면 UB 땅에서 던져서 방황하면 이미 파괴 된 객체를 파괴하려고 시도 할 것입니다. – ildjarn

+1

이동/복사 할당을위한 좋은 트릭은 간단히 [값으로 매개 변수를 가져 오는] 것입니다 (http://stackoverflow.com/questions/9746748/does-it-make-sense-to-reuse-destructor-logic-by- using-stdswap-in-a-move-assign/9746772 # 9746772). 사용자는 값 매개 변수를 이동하거나 복사 구성 (또는 구성 해제)합니다. 그런 다음'std :: swap'을 사용하여 값을 객체로 바꿀 수 있습니다. –

답변

6

절대 사용하지 않는 경우에만이 클래스에서 유형을 파생하십시오. 그렇게하면 개체가 괴물이됩니다. 표준에서 이것을 객체 수명을 설명하는 예제로 사용하는 것은 불행한 일입니다. 실제 코드에서 수행하는 것은 정말 나쁜 일입니다.

+0

새 할당 된 메모리를 수동으로 가져온 다음 배치를 새로 고치는 데에도 문제가 있습니까? 나는 이것이 스스로 허용되는지를 확인하기 위해 표준 탐구해야 할 것이다. – Yakk

+0

@Yakk no, 당신은 아무것도 할당하지 않기 때문에. –

+0

@Yakk 아니요. 원래 할당 한 객체의 크기 및 정렬 요구 사항이 새로 배치를 통해 작성한 객체에 충분하고 삭제할 때 전달하는 포인터가 적절한 유형 인 경우 해당 점에 문제가 없어야합니다. – bames53

0

기술적으로이 작은 예제에서는 소스 코드가 입니다. 그러나 현실은 Foo를 재미있게 본다면 UB를 호출 할 것입니다. 너무 무서운 정도로 안전하지 않기 때문에 완전히 가치가 없습니다. 다른 사람들처럼 스왑을 사용하십시오. 이유가 있습니다. 올바른 선택이기 때문입니다. 또한 자체 할당 검사가 잘못되었습니다.

+2

복사 및 스왑이 항상 최상의 구현 방법은 아닙니다. 강력한 예외 안전 보장을 얻는 쉬운 방법 중 하나이지만 절충안이 있습니다. Howard Hinnant가 [this] (http://stackoverflow.com/a/6687520/365496) 답변의 일부를 설명합니다. – bames53

+0

Foo 이동 과제를 호출 한 파생 클래스 작성자 (이 경우 잘못)와 관련하여 주로 우려합니까? 아니면 그보다 더 많은 문제가 있습니까? 이 기술은 하위 클래스 작성자가 사실상 무시하고 기술을 사용하도록 요구합니다.내가 생각할 수있는 대부분의 문제는 이동 할당이 가상이 아니라는 것을 포함한다. 그리고 나서 해답은이 기술이 사용되는지 여부에 상관없이 이동 할당이 가상의 경우 여야한다는 것이다. 당신은 그 이상의 우려를 가지고 있습니까? –