Library2010. 1. 19. 19:16

이번에는 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 로 사용한던지, 다른 포인터 변수에서 생성된 포인터를 사용하는 일은 습관적으로 하지 말것을 권장 !!!
Posted by 상현달