boost 의 shared_ptr 은 편한 놈이지만..
문제가 생기는 상황이 몇 가지 있다 있다. 그 중 하나 바로 객체 내부에서 전역 함수(혹은 다른 class 의 함수)를 호출 할 때 this 를 넘기는 문제인데…
왜나면 아래와 같은 코드가 안되기 때문이다.
#include
#include
using namespace boost;
class SPtrTest;
void Func(shared_ptr sp);
class SPtrTest
{
public:
int var1;
SPtrTest()
{
printf("Constructor\n");
}
~SPtrTest()
{
printf("Destructor\n");
}
void operation()
{
Func(this);
}
};
void Func(shared_ptr sp)
{
sp->var1++;
printf("%d\n", sp->var1);
};
int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr testclass(new SPtrTest);
testclass->var1 = 0;
testclass->operation();
return 0;
}
shared_ptr과 포인터형은 서로 대입이 되지 않기 때문에 위와 같은 코드는 컴파일 에러를 뱉는다. 그럼 아래와 같이 고치면 어떨까.
#include
#include
using namespace boost;
class SPtrTest;
void Func(shared_ptr sp);
class SPtrTest
{
public:
int var1;
SPtrTest()
{
printf("Constructor\n");
}
~SPtrTest()
{
printf("Destructor\n");
}
void operation()
{
shared_ptr thisptr(this);
Func(thisptr);
}
};
void Func(shared_ptr sp)
{
sp->var1++;
printf("%d\n", sp->var1);
};
int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr testclass(new SPtrTest);
testclass->var1 = 0;
testclass->operation();
return 0;
}
this 를 shared_ptr<SPtrTest> thisptr(this);
로 변환 해서 넘겻다.
이렇게 하면.
SPtrTest::Operation이 끝날때와 Func 가 끝날 때 2번 destructor 가 호출 되게 되어 에러가 난다.
이걸 방지하는 방법은 자기 자신의 shared_ptr 을 레퍼런스 카운트 문제가 생기지 않도록(this 를 넘길 때도 레퍼런스 카운터가 증가 하는) 하는 것이다.
즉 boost::enable_shared_from_this<T> 를 상속 받은 class 를 만드는 방법이다.
boost::enable_shared_from_this<T> 를 상속 받은 뒤 shared_from_this() 를 호출 하면 자기 자신의 shared_ptr 을 리턴 해 준다.
그럼 아래와 같이 된다
#include
#include
#include
using namespace boost;
class SPtrTest;
void Func(shared_ptr sp);
class SPtrTest : public boost::enable_shared_from_this
{
public:
int var1;
SPtrTest()
{
printf("Constructor\n");
}
~SPtrTest()
{
printf("Destructor\n");
}
void operation()
{
Func(shared_from_this());
}
};
void Func(shared_ptr sp)
{
sp->var1++;
printf("%d\n", sp->var1);
};
int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr testclass(new SPtrTest);
testclass->var1 = 0;
testclass->operation();
return 0;
}
이렇게 하면 아무 문제 없이 작동이 가능하다.
Ps. 특히 조심해야 할 것은..
shared_ptr<SPtrTest> thisptr(this); 를 여러 번 생성 한다고 레퍼런스 카운터가 증가하는 것은 아니다. 레퍼런스 카운터의 증가는 변수끼리의 대입에 의해서만 증가할 뿐, 저런 선언은 카운터1짜리 변수를 여러 개 늘려 에러를 내게 할 뿐이다.