문제

사용할 때 PIMPL 관용구 사용하는 것이 바람직합니까? boost:shared_ptr 대신 a std::auto_ptr? 부스트 버전이 더 예외적이라는 것을 한 번 읽었습니다.

class Foo
{
public:
    Foo();
private:
    struct impl;
    std::auto_ptr<impl> impl_;
};

class Foo
{
public:
    Foo();
private:
    struct impl;
    boost::shared_ptr<impl> impl_;
};

편집] std :: auto_ptr <>을 사용하는 것이 항상 안전합니까, 아니면 대체 부스트 스마트 포인터가 필요한 상황이 있습니까?

도움이 되었습니까?

해결책

이를 위해 std :: auto_ptr을 실제로 사용해서는 안됩니다. std :: auto_ptr을 선언 할 때 파괴자가 보이지 않으므로 제대로 호출되지 않을 수 있습니다. 이것은 PIMPL 클래스를 선언하고 다른 파일의 생성자 내부에 인스턴스를 작성한다고 가정합니다.

사용하는 경우 부스트 :: scoped_ptr (여기서 shared_ptr가 필요하지 않으면 pimpl을 다른 개체와 공유하지 않을 것이며 Scoped_ptr에 의해 시행됩니다. 비 관찰), 당신은 scoped_ptr 생성자라고 부르는 시점에서 볼 수있는 pimpl 소멸기 만 필요합니다.

예를 들어

// in MyClass.h

class Pimpl;

class MyClass 
{ 
private:
    std::auto_ptr<Pimpl> pimpl;

public: 
    MyClass();
};

// Body of these functions in MyClass.cpp

여기서 컴파일러는 MyClass의 소멸자를 생성합니다. auto_ptr의 파괴자를 호출해야합니다. auto_ptr 파괴자가 인스턴스화되는 시점에서, pimpl은 불완전한 유형입니다. 따라서 pimpl 객체를 삭제할 때 auto_ptr 파괴자에게 PIMPL 소멸자를 호출하는 방법을 모릅니다.

boost :: scoped_ptr (및 shared_ptr)에는이 문제가 없습니다. scoped_ptr (또는 재설정 메소드)의 생성자를 호출 할 때 삭제를 호출하는 대신에 사용하는 함수 포인터와 동등한 동등성이 있기 때문입니다. 여기서 핵심 요점은 PIMPL이 불완전한 유형이 아닌 경우 거래 기능을 인스턴스화한다는 것입니다. 참고로 Shared_ptr은 맞춤형 거래 기능, GDI 핸들이나 원하는 다른 것에 대해 사용할 수 있습니다. 그러나 여기에서는 필요에 대한 과잉입니다.

std :: auto_ptr을 실제로 사용하려면 pimpl이 완전히 정의 될 때 myclass.cpp에서 myclass destructor를 정의하여 추가주의를 기울여야합니다.

// in MyClass.h

class Pimpl;

class MyClass 
{ 
private:
    std::auto_ptr<Pimpl> pimpl;

public: 
    MyClass();
    ~MyClass();
};

그리고

// in MyClass.cpp

#include "Pimpl.h"

MyClass::MyClass() : pimpl(new Pimpl(blah))
{
}

MyClass::~MyClass() 
{
    // this needs to be here, even when empty
}

컴파일러는 코드가 '빈 파괴자'에서 모든 MyClass 멤버를 효과적으로 파괴합니다. 시점에서 Auto_PTR 소멸자가 인스턴스화되고, PIMPL은 더 이상 불완전하지 않으며 컴파일러는 이제 파괴자를 호출하는 방법을 알고 있습니다.

개인적으로, 나는 모든 것이 올바른지 확인하는 번거 로움이 있다고 생각하지 않습니다. 또한 누군가가 나중에 와서 겉보기에 중복 된 소멸자를 제거하여 코드를 정리할 위험이 있습니다. 따라서 Boost :: scoped_ptr와 함께 이런 종류의 일을 위해 더 안전합니다.

다른 팁

나는 사용하는 경향이있다 auto_ptr. 클래스를 검토 할 수 없게 만들어야합니다 (개인 사본 CTOR & OPERATOR = 또는 ELSE 상속 boost::noncopyable). 사용하는 경우 auto_ptr, 하나의 주름은 몸이 비어 있더라도 비 인화 소멸자를 정의해야한다는 것입니다. (컴파일러가 기본 소멸자를 생성하도록하면 impl 호출 할 때 불완전한 유형이됩니다 delete impl_ 정의되지 않은 동작을 호출하여 생성됩니다).

중에서 선택할 것이 거의 없습니다 auto_ptr & 부스트 포인터. 표준 라이브러리 대안이 할 경우 스타일 근거에서 부스트를 사용하지 않는 경향이 있습니다.

부스트 대안 std::auto_ptr ~이다 boost::scoped_ptr. 주요 차이점 auto_ptr 그게 다 boost::scoped_ptr 검사 할 수 없습니다.

보다 이 페이지 자세한 사항은.

Boost :: Shared_ptr은 PIMPL 관용구를 위해 일하기 위해 특별히 조정되었습니다. 주요 장점 중 하나는 PIMPL을 보유하고있는 클래스의 소멸자를 정의 할 수 없다는 것입니다. 공유 소유권 정책은 이점과 단점이 모두있을 수 있습니다. 그러나 나중에는 사본 생성자를 올바르게 정의 할 수 있습니다.

당신이 정말로 성가신다면 auto_ptr 회원은 전체 정의가 필요하지 않습니다 auto_ptr사용되는 지점의 템플릿 매개 변수. 그 말을했지만, 나는 이것이 효과가없는 것을 본 적이 없습니다.

한 가지 변형은 a를 사용하는 것입니다 const auto_ptr. 이것은 초기 목록 내부에 새로운 표현식으로 'PIMPL'을 구성하고 컴파일러를 보장 할 수있는 한 할 수 없습니다 기본 사본 생성자 및 할당 방법을 생성합니다. 동봉 클래스를위한 비 인화 소멸자는 여전히 제공되어야합니다.

다른 것들이 평등하게, 나는 표준 라이브러리만을 더 휴대용으로 유지하기 때문에 구현을 선호합니다.

복사 가능한 클래스를 원한다면 사용하십시오 scoped_ptr, 복사를 금지하므로 클래스를 기본적으로 잘못 사용하기 어렵게 만듭니다 (사용과 비교하여 shared_ptr, 컴파일러는 자체적으로 카피 시설을 방출하지 않습니다. 그리고 경우에 shared_ptr, 당신이 당신이 무엇을하는지 알지 못하면 [마법사들조차도 종종 충분한 경우], 갑자기 무언가의 사본이 그 무언가를 수정할 때 이상한 행동이있을 것입니다. -과제:

class CopyableFoo {
public:
    ...
    CopyableFoo (const CopyableFoo&);
    CopyableFoo& operator= (const CopyableFoo&);
private:
    scoped_ptr<Impl> impl_;
};

...
CopyableFoo (const CopyableFoo& rhs)
    : impl_(new Impl (*rhs.impl_))
{}

shared_ptr은 pimpl의 auto_ptr보다 훨씬 바람직합니다. 외부 클래스는 갑자기 복사 할 때 포인터를 잃을 수 있기 때문입니다.

shared_ptr을 사용하면 정전으로 선고 된 유형을 사용하여 작동 할 수 있습니다. auto_ptr는 정전기 유형을 허용하지 않습니다. scoped_ptr도 마찬가지이며, 외부 클래스가 외부 클래스가 공포 할 수없고 하나의 포인터 만 있으면 일반적인 것일 수도 있습니다.

PIMPL에서 침입 참조 카운트를 사용하고 외부 클래스가 사본을 호출하고 구현에 의미론을 할당하도록 할 말이 많습니다. 이것이 진정한 공급 업체 (클래스 공급) 모델이라고 가정하면 공급 업체가 사용자가 Shared_PTR을 사용하거나 동일한 버전의 Shared_PTR (Boost 또는 STD)을 사용하도록 강요하지 않는 것이 좋습니다.

나는 정말로 행복했다 Vladimir Batov의 Imple_ptr [modified. 명시 적 카피 구성 및 할당 연산자를 만들 필요없이 PIMPL을 쉽게 만들 수 있습니다.

원래 코드를 수정 했으므로 이제 shared_ptr과 비슷하므로 Epilog 코드에서 사용할 수 있으며 빠른 상태로 유지됩니다.

C ++에서는 많은 기회가 있습니다. :) 객체가 언제 들어가야하는시기를 완벽하게 알기 때문에 (당신의 내에서, 당신의 내에서 당신은 당신은 당신이 얼마나 많은 기회를 사용할 필요가 없습니다. 생성자 및 소멸자).

간단하게 유지하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top