2008-09-26 3 views
76
)

코드에서 boost:shared_ptr을 광범위하게 사용하고 있습니다. 실제로 힙에 할당 된 대부분의 개체는 shared_ptr에 의해 보관됩니다. 불행하게도 이것은 shared_ptr을 취하는 모든 함수에 this을 전달할 수 없다는 것을 의미합니다. 다음 코드를 고려하십시오.boost :: shared_ptr 받기 (

void bar(boost::shared_ptr<Foo> pFoo) 
{ 
    ... 
} 

void Foo::someFunction() 
{ 
    bar(this); 
} 

여기에는 두 가지 문제점이 있습니다. 첫째, shared_ptr의 T * 생성자가 명시 적이기 때문에 컴파일되지 않습니다. 둘째로, 내가 강제로 bar(boost::shared_ptr<Foo>(this))으로 빌드하도록 만들면 결국 두 번 삭제 될 수있는 객체에 대한 두 번째 공유 포인터가 생성됩니다.

이것은 제 질문에 대한 것입니다 : 당신이 알고있는 기존 공유 포인터의 사본을 얻기위한 표준 패턴이 그 객체 중 하나의 메소드 내부에서 존재합니까? 내 유일한 옵션을 여기에 집계하는 침입 참조를 사용하고 있습니까?

+0

"침입 참조 여기 내 유일한 옵션을 계산을 사용하여 _Is _ "이 옵션의 문제점은 무엇입니까? – curiousguy

+0

아무 것도 아닐 수도 있습니다. 상황에 따라 다릅니다. 그것은 당신의 객체를 더 크게 만들고 당신이 스마트 포인터를 유지하고있는 클래스를 제어 할 수없는 장소에서는 작동하지 않을 수 있습니다. –

+0

enabe_shared_from_this는 이제'std ::'에 있습니다. 내 대답 좀 봐. –

답변

102

당신은 enable_shared_from_this에서 파생 수 있습니다 확인 한 다음 "이"자신의 자기 객체에 공유 포인터를 생성하는 대신 "() shared_from_this"를 사용할 수 있습니다. 링크에서

예 :

#include <boost/enable_shared_from_this.hpp> 

class Y: public boost::enable_shared_from_this<Y> 
{ 
public: 

    shared_ptr<Y> f() 
    { 
     return shared_from_this(); 
    } 
} 

int main() 
{ 
    shared_ptr<Y> p(new Y); 
    shared_ptr<Y> q = p->f(); 
    assert(p == q); 
    assert(!(p < q || q < p)); // p and q must share ownership 
} 

그것은 멤버 함수에서 산란 스레드를 높일 수있는 좋은 아이디어 :: shared_from_this에 바인딩()의 대신이의. 개체가 릴리스되지 않도록합니다.

+0

f()는 ".Copy()"와 유사하며 얕은 사본이기도합니다. –

9

바 내부에 pFoo의 공유 사본을 만들고 있습니까? 당신이 내부 미친 작업을 수행하지 않는, 그냥 이렇게 :


void bar(Foo &foo) 
{ 
    // ... 
} 
3
포인터를 받아들이는 기능을하고 싶어

두 가지 행동 중 하나를

  • 객체가 전달되고 소유 및 범위를 벗어날 때 삭제하십시오. 이 경우, X *를 받아들이고 scoped_ptr을 (함수 본문에서) 해당 오브젝트 주위로 즉시 랩핑 할 수 있습니다. 이것은 "this"또는 일반적으로 힙 할당 객체를 허용하기 위해 작동합니다.
  • 공유 포인터 (그것을 소유하지 않은) 객체에 전달된다.이 경우 당신이 할 하지 당신이에서 개체를 삭제하지 않기 때문에, 전혀 scoped_ptr를 사용하려는 당신의 기능의 끝. 이 경우 이론적으로 원하는 것은 shared_ptr입니다 (다른 곳에서는 linked_ptr이라고 불렀습니다). 부스트 라이브러리는 a version of shared_ptr이며, Scott Meyers의 Effective C++ 서적 (3 판 18 항)에서도 권장됩니다.

편집 : 아차 나는 약간 질문을 오해, 나는 지금이 대답은 정확하게 문제를 해결하지 않습니다를 참조하십시오. 어쨌든이 코드는 비슷한 코드로 작업하는 사람들에게 도움이 될 수 있습니다.

19

shared_ptr 대신 함수 매개 변수에 원시 포인터를 사용하십시오. 스마트 포인터의 목적은 객체의 수명을 제어하는 ​​것이지만 객체 수명은 C++ 범위 지정 규칙에 의해 이미 보장되어 있습니다. 함수 수명이 끝날 때까지 존재합니다.즉, 함수가 반환되기 전에 호출 코드가 객체를 삭제할 수 없습니다. 따라서 함수 내에서 객체를 삭제하려고 시도하지 않는 한 "멍청한"포인터의 안전성이 보장됩니다.

함수에 shared_ptr을 전달해야하는 경우는 개체의 소유권을 함수에 전달하거나 함수가 포인터의 복사본을 만들도록하려는 경우입니다.

+1

동의. 여러 번 foo (const Object * object_ptr) {} foo (obj.get());를 사용할 수 있습니다. obj는 boost :: shared_ptr < Object >입니다. 웹에서 Herb Sutter를 (를) 검색하면이 유사 문제에 대한 훌륭한 정보가있는 다른 기사 작성자입니다. –

+1

포인트 옆에 약간 있지만, ... 포인터를 사용할 수 있다면, (아마도) 당신은 더 나은 IMO 인 레퍼런스를 사용할 수 있습니다. –

+1

@ denis-bu,'NULL' 포인터가 가능성을 제외하고는. 그러나 당신은 좋은 지적을합니다. –

5

C++ 11 shared_ptrenable_shared_from_this은 이제 표준 라이브러리에 포함됩니다. 후자는 이름에서 알 수 있듯이이 경우에 정확하게 적용됩니다. 위의 링크에서 해당에

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

예 기지 :

struct Good: std::enable_shared_from_this<Good>{ 
    std::shared_ptr<Good> getptr() { 
     return shared_from_this(); 
    } 
}; 

사용 :

std::shared_ptr<Good> gp1(new Good); 
std::shared_ptr<Good> gp2 = gp1->getptr(); 
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n'; 
관련 문제