안녕하세요? nicekr.황경록 입니다.
오늘 배워볼 내용은 스마트 포인터에 대한 내용입니다.
부스트 라이브러리에서 제공하는 스마트 포인터는 5개의 템플릿 클래스로 이루어져 있습니다.
그중에서 shared_ptr 은 어떤 객체가 인스턴스화 되었을 때 이 실체를 레퍼런스(참고)하는
객체가 없을 때 까지 소멸되지 않음을 기본으로 합니다.
자 그럼 다음 샘플 코드를 보며 설명을 하겠습니다.
샘플은 C++ Builder 에서 Console Wizard 를 사용하여 만들었습니다.
아시겠지만 샘플을 컴파일해 보려면 당연히 부스트 라이브러리가 설치되어 있고 빌더에서
그 환경이 설정되어 있어야 합니다. 이 부분에 대한 내용은 <설치 편>을 참고 하십시오.
그럼 이제 코드로 들어가 보도록 하겠습니다.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <stdio.h>
///////////////////////////////////////////////////////////////////////
// 부스트 라이브러리의 shart_ptr을 사용하기 위한 준비 작업으로
// shared_ptr.hpp 를 포함시켜야 한다.
#include <boost\shared_ptr.hpp>
// 네임스페이스도 추가해 주자.
using boost::shared_ptr;
//---------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////
// C++ Builder IDE 의 이벤트 로그 창에 디버깅 메시지를 출력하도록 하는
// OutputDebugString의 약간(!) 확장판 함수를 제작하자.
// 인자를 받도록 추가한 것 뿐...
//
// 빌더의 IDE 환경에서 Ctrl + Alt + V 키를 누르면 이벤트 로그 창을
// 확인할 수 있다.
int DBG_PRINTF(const char * __format, ...)
{
va_list argptr;
int nRet;
char czLog[MAX_PATH] = { 0x00, };
va_start(argptr, __format);
nRet = vsprintf(czLog, __format, argptr);
va_end(argptr);
OutputDebugString(czLog);
return nRet;
}
// 의미를 좀 더 명확히 하기 위해...
#define GTRACE DBG_PRINTF
///////////////////////////////////////////////////////////////////////
// shared_ptr에 대한 Instance를 create하기 위한 interface class
//
// 단위 전략적 마인드에 의거 ^^''' 실제는 별볼일 없어 보이지만
// 개인적으로는 이런 스타일을 좋아라 한다.
// 템플릿 인자의 타입을 shared_ptr 에 embrace 해서 생성하도록 한다.
template<class TYPE>
class ISharedPtr
{
typedef shared_ptr<TYPE> T_sp;
public:
static T_sp CreatePtr(void)
{
T_sp spNew(new TYPE());
return spNew;
}
};
///////////////////////////////////////////////////////////////////////
// Test 목적으로 만든 클래스
// 인스턴스화 될때 생성된 인스턴스에 Id 를 발급해서 개개의 생성된
// 인스턴스를 확인 할 수 있도록 했다.
static volatile LONG g_nCreationOrder = 0;
volatile LONG GetCreationOrder(void) { return InterlockedIncrement(&g_nCreationOrder); };
class CTestObj;
typedef shared_ptr<CTestObj> CTestObj_sp;
class CTestObj
{
public:
CTestObj() { m_nOrder = GetCreationOrder(); }
virtual ~CTestObj() { GTRACE(">>> I'm dying! from %d \n", m_nOrder); }
public:
void WhoAmI(void) { GTRACE(">>> i'm %d \n", m_nOrder); }
private:
LONG m_nOrder;
};
///////////////////////////////////////////////////////////////////////
#pragma argsused
int main(int argc, char* argv[])
{
CTestObj_sp spFirst; // 선언하고....
spFirst = ISharedPtr<CTestObj>::CreatePtr(); // 인스턴스화 했다.
spFirst->WhoAmI(); // 난 생성된 1번 인스턴스
{
CTestObj_sp spSecond(ISharedPtr<CTestObj>::CreatePtr()); // 인스턴스화 했다.
spSecond->WhoAmI(); // 난 생성된 2번 인스턴스
// -_- 1번의 인스턴스는 파괴된다. 왜냐하면 더이상의 참조가 없어지므로
// 2번의 참조 카운트가 2로 된다.
spFirst = spSecond;
}
// 무뉘만 1번... 이전 블럭에서 2번으로 참조가 바뀌어 버렸다.
// 블럭을 벗어나면서 참조가 1로 줄게 된다. 블럭 로컬 변수...
spFirst->WhoAmI(); // 난 ~ 블럭에서 1번을 죽이고 살아난 2번 입니다~
return 0;
}
//---------------------------------------------------------------------------
코드를 보시면 알겠지만 스마트 포인터라는 건 아주 심플하면서 유용한 도구 입니다.
그 원리를 잘 알고 필요한 부분에 사용하게 된다면 ~.~ 좋겠죠?
그럼 실제 빌더 IDE 의 이벤트 로그 부분을 올리며 첫번째 shared_ptr 템플릿 클래스에
대한 강좌를 마칩니다.
항상 건강!하세요!
----
ODS: >>> i'm 1 Process SharedPtr_01.exe (0xA14)
ODS: >>> i'm 2 Process SharedPtr_01.exe (0xA14)
ODS: >>> I'm dying! from 1 Process SharedPtr_01.exe (0xA14)
ODS: >>> i'm 2 Process SharedPtr_01.exe (0xA14)
ODS: >>> I'm dying! from 2 Process SharedPtr_01.exe (0xA14)
|