이번에는 Smart Pointer 이다. new 해서 사용해도 delete 할필요가 없다.
Java 나 C# 에서와 같이 자기참조 카운터를 관리하고 카비지 컬렉터도 가지고 있다. 물론 다중스레드에서도 안전하다.
#include <boost/tr1/tr1/memory> 해더가 필요하다.
기본 사용법
int _tmain(int argc, _TCHAR* argv[])
{
std::tr1::shared_ptr sp1(new int);
*sp1 = 1; // 값 대입
std::tr1::shared_ptr sp2(new int(5));
std::cout << "sp1 의 값:" << *sp1 << std::endl;
std::cout << "sp1 의 주소:" << sp1 << std::endl;
std::cout << "sp2 의 값:" << *sp2 << std::endl;
std::cout << "sp2 의 주소:" << sp2 << std::endl;
std::cout << std::endl;
*sp1 = *sp2; //call by value
sp2.reset(new int(9));
std::cout << "sp1 의 값:" << *sp1 << std::endl;
std::cout << "sp1 의 주소:" << sp1 << std::endl;
std::cout << "sp2 의 값:" << *sp2 << std::endl;
std::cout << "sp2 의 주소:" << sp2 << std::endl;
std::cout << std::endl;
sp1 = sp2; //call by reference
*sp1 = 7;
std::cout << "sp1 의 값:" << *sp1 << std::endl;
std::cout << "sp1 의 주소:" << sp1 << std::endl;
std::cout << "sp2 의 값:" << *sp2 << std::endl;
std::cout << "sp2 의 주소:" << sp2 << std::endl;
return 0;
}
실행결과:
sp1 의 값:1
sp1 의 주소:00032F78
sp2 의 값:5
sp2 의 주소:00032FE8
sp1 의 값:5
sp1 의 주소:00032F78
sp2 의 값:9
sp2 의 주소:000313D8
sp1 의 값:7
sp1 의 주소:000313D8
sp2 의 값:7
sp2 의 주소:000313D8
메모리 해제를 사용자 정의 함수로 처리가 가능하다.
class deleter
{
public:
void operator()(int *p)
{
std::cout << "delete_operator" << std::endl;
delete p;
}
static void Deleter(int* p)
{
std::cout << "delete_static_method" << std::endl;
delete p;
}
};
void deleter_method(int *p)
{
std::cout << "delete_method" << std::endl;
delete p;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::tr1::shared_ptr sp1(new int(5), deleter());
std::tr1::shared_ptr sp2(new int(5), deleter_method);
std::tr1::shared_ptr sp3(new int(5), deleter::Deleter);
return 0;
}
실행결과:
delete_static_method
delete_method
delete_operator
응용편~ 요런걸 사용해도 메모리 해제의 부담이 없다.
class Animal_Interface
{
public:
virtual void Crying() = 0;
};
class Animal_dog : public Animal_Interface
{
public:
void Crying() {std::cout << "멍멍멍 !!!" << std::endl;};
};
class Animal_cat : public Animal_Interface
{
public:
void Crying() {std::cout << "야옹~" << std::endl;};
};
int _tmain(int argc, _TCHAR* argv[])
{
std::tr1::shared_ptr dog(new Animal_dog);
std::tr1::shared_ptr cat(new Animal_cat);
dog->Crying();
cat->Crying();
return 0;
}
실행결과:
멍멍멍 !!!
야옹~
주의 할점 !!! shared_ptr 을 사용할때 하나의 포인터를 두개의 shared_ptr 이 참조하면 두번 삭제(delete) 하므로 crash를 발생할 수 있다.
void Crash_Double_Ref_1()
{
int* p = new int;
std::tr1::shared_ptr sp1(p);
std::tr1::shared_ptr sp2(p);
}
//함수가 종료되면 스레드 스텍에서 sp1 이 p 를 제거(delete) 하고
//sp2 가 또 p 를 제거 하므로 sp2 가 제거할때 crash 발생한다.
void Crash_Double_Ref_2(int* p)
{
std::tr1::shared_ptr sp1(p);
}
//함수가 종료되면 sp1 이 p 를 제거(delete)한다.
int _tmain(int argc, _TCHAR* argv[])
{
Crash_Double_Ref_1();
int* p = new int;
Crash_Double_Ref_2(p);
delete p;
//Crash_Double_Ref_2 가 p 를 제거 했기 때문에 delete 할때 crash
return 0;
}
하나의 포인터를 두개의 shared_ptr 로 사용한던지, 다른 포인터 변수에서 생성된 포인터를 사용하는 일은 습관적으로 하지 말것을 권장 !!!