2016-12-10 11 views
2

은이 표에 따라 unique_ptr 소멸자가 T가 완료 필요 포워드 선언 된 유형 T에 대한 unique_ptr<T>를 사용하지만, 이동 할당 연산자뿐만 아니라 (그리고 reset) 때 :C++/pimpl : 원시 포인터 또는 unique_ptr? 더 나은 선택은 무엇입니까?

https://stackoverflow.com/a/6089065/1794803

그래서 당신의 pImpl 관용구를 들어, deletemove assignment method를 선언해야 제대로 구현 (부작용으로, 비 인라인을 표시하는) :

class impl_t; 

class A 
{ 
    std::unique_ptr<impl_t> p_impl; 

public: 
    // Implement in A.cpp as A::~A() = default; 
    ~A(); 

    // Implemented in A.cpp as A& operator=(A&&) = default; 
    A& operator=(A&& he); 
}; 

그러나 std::unique_ptr은 동적 메모리를위한 RAII 솔루션이므로 pImpl은 이미 클래스 안에 있으며 소멸자를 작성해야합니다. 클래스가이기 때문에 원시 포인터를 관리하는 것이 더 낫지 않습니까? 이미 RAII 같은 p_impl의 관점에서 :

class impl_t; 

class A 
{ 
    impl_t* p_impl; 

public: 
    ~A(); // The destructor must be written anyway. 

    // The omitted move assignment destructor doesn't cause UB. 
}; 

하지 더 나은 솔루션인가요? (+ 정의 또는 자신의 복사/이동 연산자를 삭제하려면 클래스를 복사 할 수/이동 여부;하지만 그것은 "의식적인 선택"이지만, unique_ptr에 대한 이동 지정을 쓰지 않는 것은 오류입니다.)

unique_ptr을 사용하면 어쨌든 선언해야하는 소멸자에만 delete p_impl이 저장됩니다.

unique_ptr은 예외의 경우에도 파괴되지만 "속성"의 경우 로컬 객체에 대한 탁월한 선택입니다. 이동을 다시 작성해야한다는 것을 기억하지 않으면 UB를 얻을 수있는 가능성 만 남습니다. 할당 연산자.

답변

4

음은 std::unique_ptr을 사용하면 p_impl에 대한 명시 적 delete으로 괴롭 히고에서 당신을 구속.

동시 액세스 및 예외적 인 경우에는 생성자에서 잘 작동합니다 (원시 포인터 및 new 자신을 사용하여 보장되지 않는 것).

+0

또한, 커스텀 Deleter를 가지지 않는'std :: unique_ptr'는 일단 최적화되면 크기면에서 미가공 포인터와 유사합니다. – skypjack

0

std :: unique_ptr은 pimpl에 따라 선호되는 방법이어야합니다. 참고로 약 10 분 후 Herb Sutter's talk at CppCon16을 참조하십시오. 이유는 RAII를 유지하면서 실수로 여드름을 바꾸는 것을 방지 할 수 있기 때문입니다.