http://breaklee.blog.me/60137887986

shared_ptr 은 간단하게 설명하자면, 가리키고 있는 객체의 수를 관리(참조 카운트)하고, 

참조하고 있는 객체의 수가 0 이되면 자동으로 삭제시켜주는 smart pointer 입니다.


소멸자 보면, _Decref() 라는 함수를 호출하고 있습니다. 뭐구현마다 조금씩 차이는 있겠지만,

내부적으로 ref count  관리하고 하나씩 줄여주는 역할을 합니다.

당연히, ref count  0  되면제어하고 있는 객체를 delete 합니다.


 ~shared_ptr()

      {       // release resource

              this->_Decref();

      }

           

void _Decref()

{       // decrement use count

        if (_MT_DECR(_Mtx, _Uses) == 0)

        {       // destroy managed resource, decrement weak reference count

               _Destroy();

               _Decwref();

        }

 }


     

오버로딩 된 생성자를 살펴보면 std::auto_ptr 을 인자로 받는 생성자가 보입니다auto_ptr release()  호출합니다. 

shared_ptr  공유하려는 목적으로 사용한다면 의도와는 다르게 auto_ptr 은, 그 후로는 사용할  없게 됩니다.

auto_ptr 참조 http://breaklee.blog.me/60123428473 ]

 

template<class _Ty2>

      explicit shared_ptr(auto_ptr<_Ty2>& _Other)

      {       // construct shared_ptr object that owns *_Other.get()

               this->_Reset(_Other);

      }

 

template<class _Ty2>

      void _Reset(auto_ptr<_Ty2>& _Other)

      {       // release resource and take _Other.get()

               _Ty2 *_Px = _Other.get();

               _Reset(_Px, new _Ref_count<_Elem>(_Px));

               _Other.release();

      }



한가지 재미는건, bool type 으로 캐스팅  경우객체의 상태를 질의   있다는 건데요.

 

operator _STD _Bool_type() const

      {       // test if shared_ptr object owns no resource

              return (this->_Get() != 0 ? _CONVERTIBLE_TO_TRUE : 0);

      }


  

결국엔 객체의 주소값으로 TRUE 임을 알려주고 있습니다간단한 이해를 위해서 boost  잠시 보시면


 operator bool () const

{

return px != 0;

}


 

그냥 shared_ptr 객체가 가리키고 있는 곳이  아니면 true  리턴하게 되어 있습니다.

오류나 의도치 않은 연산의 방지를 위해(표준 때문에), tr1에서는 멤버 함수의 포인터를 반환하여 예방하고 있습니다.

[출처] shared_ptr|작성자 breaklee







http://humnya.egloos.com/2913729


shared_ptr을 c++ 형식으로 타입 캐스팅 하고 싶을 때는

static_pointer_cast<type> var;
dynamic_pointer_cast<type> var;
static_pointer_cast<type> var;



http://crowmaniac.net/boostshared_ptr%EC%97%90-%EA%B4%80%ED%95%B4/

3. shared_ptr의 파괴동작.

shared_ptr을 단순히 new/delete를 이용해 생성/파괴하는 객체에만 사용할 수 있다는 생각은 크나큰 오산입니다. Custom Destructor를 세팅할 수 있게 해주는 기능은 shared_ptr의 가능성을 대폭 증가시켜 줍니다. :)

01#include <boost/shared_ptr.hpp>
02// 사실 싫어하는 예이지만, HANDLE을 예로 들고 싶기에 어쩔수.. 없;;
03#include <windows.h>
04typedef boost::shared_ptr<void> HANDLESP;
05 
06void test8()
07{
08HANDLE h = ...(뭐든 핸들을 받아온다)...
09HANDLESP hsp = HANDLESP(h, CloseHandle);
10}// hsp가 파괴될때 CloseHandle(h)가 호출된다.

hsp를 생성할때 보면, 뒤쪽에 CloseHandle이란 함수를 넣어주는 것을 발견할 수 있습니다. CloseHandle의 위치에는 HANDLE(정확히는 void*)을 매개변수로 받는 호출가능한 C++객체는 무엇이든 올 수 있습니다. :)

즉, 객체가 C++ 표준인 new/delete를 이용해 할당되지 않더라도 파괴될때 호출할 호출가능한 객체를 지정해주면, delete대신 그 함수를 통해 객체를 파괴하게 되지요.

DLL 사이에서 객체를 주고 받을 때도 매우 유용합니다. DLL A에서 생성한 객체를 DLL B에서 파괴할 경우 문제가 발생하기 때문에, A의 인터페이스에 객체를 삭제하는 함수를 등록시켜서 쓰는 것이 일반적인데, 이런 경우에도 객체를 삭제하는 함수를 파괴시 호출할 함수로 지정해주면 간단히 shared_ptr을 적용할 수 있는 것이지요. 이때, 전에 설명했던 boost::bind가 큰 힘을 발휘하는 경우가 많답니다.




http://harmonize84.tistory.com/130


shared_static_cast


My Program-*/C+ 2009/11/16 13:21
  1. class CBase  
  2. {  
  3. };  
  4.   
  5. class CDerived : public CBase  
  6. {  
  7. };  
  8.   
  9. std::map<int, boost::shared_ptr<CBase>> mapTest;  
  10.   
  11.   
  12. boost::shared_ptr<CDerived> TestFunc(void)  
  13. {  
  14.     boost::shared_ptr<CBase> pTest(new CDerived);  
  15.   
  16.     mapTest.insert(std::map<int, boost::shared_ptr<CBase>>::value_type(0, pTest));  
  17.   
  18.     std::map<int, boost::shared_ptr<CBase>>::iterator iter = mapTest.find(0);  
  19.   
  20.     return boost::shared_ptr<CDerived>(static_cast<CDerived*>(iter->second.get()));      // 문제의 장소  
  21. }  
  22.   
  23. int main(void)  
  24. {  
  25.     boost::shared_ptr<CDerived> pInv = TestFunc();  
  26.   
  27.     return 0;  
  28. }  


인터페이스 클래스를 설계하면서 부딪힌 문제이다.

위 코드는 2가지 문제가 있다. 
(일단 위 코드는 런타임 에러로 _BLOCK_TYPE_IS_VALID_가 나는데 이는 포인터가 잡혀 있지 않다는 의미)

첫번째는 shared_ptr의 임시객체에 map에 있는 shared_ptr의 원시포인터를 반환한다는 점

두번째는 shared_ptr에 담긴 객체의 포인터를 static_cast로 변환한다는 점이다.

사실 이 두가지 문제는 하나로 귀결되는데 그것은 boost에서 지원하는 캐스팅을 통하여

이 값을 그대로 넘겨주는 방법이 그것이다.

이 방법을 몰라서 객체의 포인터를 캐스팅변환을 통하여 임시객체에 넣고 그것을 반환하는 형식의

코드를 작성했는데 임시객체에 들어감으로써 그것은 map에서 가지고있는 카운팅이 올라가는 것이 아닌

또다른 하나의 스마트 포인터가 생성된 것이다. 이미 해제된 메모리에 대해 해제를 시도하니 에러는 당연지사

아래 코드는 위의 문제를 해결한 코드이다.

  1. boost::shared_ptr<CDerived> TestFunc(void)  
  2. {  
  3.     boost::shared_ptr<CBase> pTest(new CDerived);  
  4.   
  5.     mapTest.insert(std::map<int, boost::shared_ptr<CBase>>::value_type(0, pTest));  
  6.   
  7.     std::map<int, boost::shared_ptr<CBase>>::iterator iter = mapTest.find(0);  
  8.   
  9.     return boost::shared_static_cast<CDerived>(iter->second);  
  10.     //return boost::shared_ptr<CDerived>(static_cast<CDerived*>(iter->second.get()));        // 문제의 코드  
  11. }  


이 문제때문에 2일을 허비했다. 중간에 결혼식도 있고 하여 정상적인 작업이 불가능 했지만.





http://blog.naver.com/jungwan82?Redirect=Log&logNo=20120508129


클래스내에서 자신에 대한 shared_ptr 리턴하기





아래처럼 쓰면 안되고..


#include <iostream>

#include <boost/shared_ptr.hpp>


class A

{

public:

boost::shared_ptr<A> test()

{

boost::shared_ptr<A> pFromThis(this); // <- this part is dangerous.

return pFromThis;

}

};


int main(int argc, _TCHAR* argv[])

{

boost::shared_ptr<A> p(new A);

boost::shared_ptr<A> p2 = p->test();

std::cout << p.use_count() << std::endl;

p->test();


getchar();

return 0;

}


위의 용법의 특이점은 this 를 이용해서  shared_ptr를 만들어낸다는 것이다. cout에 출력되는 use_count()값은 기대값인 2가 아니라 1이 되어 버리는데 이유는 this가  A const* 형이기 때문인 것으로 추정된다. 위의 예제에서 우리는 shared_ptr<A>의 인스턴스가 2개 존재하는 것으로 기대하는데 use_count()가 1이라는 것은 아직도 필요한 포인터가 delete 되어버릴 수 있다는 것을 의미한다.


해결방법은 아래와 같다.


#include <iostream>

#include <boost/enable_shared_from_this.hpp>

#include <boost/shared_ptr.hpp>


class A : public boost::enable_shared_from_this<A>

{

public:

boost::shared_ptr<A> test()

{

return shared_from_this();

}

};


int main(int argc, _TCHAR* argv[])

{

boost::shared_ptr<A> p(new A);

boost::shared_ptr<A> p2 = p->test();


std::cout << "shared_count = " << p.use_count() << std::endl;



getchar();


return 0;

}




반응형

'메타프로그래밍 > Boost::' 카테고리의 다른 글

boost::thread  (0) 2012.12.25
boost::weak_ptr  (0) 2012.11.24
boost::function  (0) 2012.11.13
boost::unordered_set  (0) 2012.11.13
Boost::[bind, mem_fn ] 과 STL , 멤버함수 조합사용  (0) 2012.11.13

+ Recent posts