2013-08-21 2 views
0

누군가 아래 나와 같이 사용하면이 두 가지 방법의 차이점을 말해 줄 수 있습니까?부스트 :: shared_ptr 반환 및 반환 된 원시 포인터에서 boost :: shared_ptr 생성 사이의 차이점은 무엇입니까?

CreateBoostContainer를 사용하면 코드가 잘 작동합니다. 그러나 CreateContainer를 사용하면 ContainerC에서 shared_from_this를 사용하려고 할 때 나중에 Foo 함수의 코드에서 boost :: bad_weak_ptr 예외가 발생합니다. 하나의 스레드 만 사용하고 있습니다.

감사합니다.

사용법 :

SceneElementNodeC* poNode(new SceneElementNodeC(CreateBoostContainer())); 
SceneElementNodeC* poNode(new SceneElementNodeC(boost::shared_ptr<SceneElementI>(CreateContainer()))); 

정의 :

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    return boost::shared_ptr<SceneElementI>(new ContainerC()); 
} 

SceneElementI* LoaderC::CreateContainer() const 
{ 
    return new ContainerC(); 
} 

SceneElementNodeC :

class SceneElementNodeC 
{ 
    SceneElementNodeC(boost::shared_ptr<SceneElementI> spSceneElement) 
    : m_spSceneElement(spSceneElement) 
    {}; 
} 

ContainerC :

class ContainerC : public SceneElementI, public boost::enable_shared_from_this<ContainerC> 
{ 
    ContainerC() 
    {}; 

    void Foo(VisitorI* poVisitor) 
    { 
     poVisitor->Visit(shared_from_this()); 
    }; 
} 

답변

1

첫째, CreateBoostContainer끔찍한 이름은, 부스트 라이브러리는 여러 컨테이너를 포함하여 수백 가지의 구성 요소를 포함 shared_ptr 부스트의 한 작은 부분이다. 나중에 std::shared_ptr을 반환하도록 코드를 변경 한 경우 함수의 이름을 바꿔야하므로 CreateStdContainer으로 변경하겠습니까?!

두 번째로 문제를 재현 할 수있는 완전한 코드를 제공하지 못했습니다. 따라서 Stackoverflow 규칙에 따라 질문을 닫아야합니다!나는 당신의 유형은 다음과 같이 정의되어 있다고 추측하고있다 :

class ContainerC 
: public SceneElementI, public boost::enable_shared_from_this<ContainerC> 
{ 
    // ... 
}; 

의 차이는이 기능에 있다는 것입니다 :

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    return boost::shared_ptr<SceneElementI>(new ContainerC()); 
} 

당신은 ContainerC* 그래서 shared_ptr 생성자와 shared_ptr이 있음을 감지 할 수 초기화가

,617 ( enable_shared_from_this<ContainerC>에 내재 업 캐스팅 써) enable_shared_from_this 기본 클래스이 함수 반면

SceneElementI* LoaderC::CreateContainer() const 
{ 
    return new ContainerC(); 
} 

shared_ptr을 만들기 전에 포인터를 기본 클래스로 변환하여 개체의 동적 유형에 대한 정보를 잃게됩니다. 반환 된 포인터는 SceneElementI*이고 enable_shared_from_this 기본 클래스가 없으므로 포인터가 나중에 shared_ptr을 초기화하는 데 사용되면 해당 포인터가 파생 된 유형의 기본 클래스를 가리킨다는 것을 알 수 없습니다. enable_shared_from_this<ContainerC>.

당신은 첫 번째 함수는이 작업을 수행하여 작동하지 않을 만들 수 :이 동일합니다

boost::shared_ptr<SceneElementI> LoaderC::CreateBoostContainer() const 
{ 
    SceneElementI* ptr = new ContainerC(); 
    return boost::shared_ptr<SceneElementI>(ptr); 
} 

, 그것은 shared_ptr를 작성하기 전에 SceneElement* 포인터로 변환하기 때문이다.

shared_ptr는 똑똑하고 해당이 shared_ptr에 저장되는 유형이 아닌 경우에도 그것을 구성 포인터 타입을 사용한다, 그래서 포인터 업 캐스팅 당신이 경우 먼저 shared_ptr 영리 할 수 ​​없습니다.

+0

먼저 차이점을 상세히 설명해 주셔서 감사 드리며 정확히 이해하지 못했습니다. – schluchc

+0

CreateBoostContainer의 이름에 대해서는 물론 끔찍하지만이 질문에서 두 함수를 구별하는 것이 었습니다. 두 번째 요점에 대해서, 당신 말이 맞습니다. 그러나 나는 그런 경우에 여전히 질문을 향상시킬 수있는 기회가 있기를 바랍니다. – schluchc

1

Documentation for enable_shared_from_this

이 필요합니다 enable_shared_from_this은 *이 형 T의 인스턴스 t의 하위 객체해야 T.의 접근 기본 클래스 해야합니다. 거기에 은 t를 소유 한 적어도 하나의 shared_ptr 인스턴스 p가 존재해야합니다.

주, "은 t을 소유하고 적어도 하나의 shared_ptr의 인스턴스 쪽이 존재해야합니다."

CreateContainer을 사용하는 경우 소유하고있는 인스턴스가 shared_ptr이 아닙니다.

+0

구성된 SceneElementNodeC가 shared_pointer를 소유하고 있으므로 하나가 있습니까? 아니면 제가 잘못 됐습니까? – schluchc

1

Using the raw pointer at all is poor form. 따라서 메모리 누출을 방지하려면 std::make_shared과 같은 것을 사용하는 것이 일반적입니다. 클래스를 새로 작성한 시점과 스마트 포인터와 관련된 시점 사이에 예외가 발생할 수 있습니다.

그런데, 이것은 단지 부스트의 enable_shared_from_this 작동 방식에 대한 구현 세부 사항이라고 생각합니다.

+0

구현 세부 사항이라 할지라도 첫 번째 또는 두 번째 방법 중 무엇을 사용하는지 여부는 무엇입니까? 나는 shared_from_this가 사용되는 순간에 어떤 차이점을 보지 못했습니다. 이것은 생성 된 SceneElementNodeC가 shared_pointer를 소유하고있을 때입니다. – schluchc

관련 문제