본문 바로가기

Software/C++

C++ Smart Pointer 참조계수 기반

C++ Smart Pointer는  Pointer일반기능(복사,생성,대입,)과  자동 Memory해제 기능을 지원하는 객체를 말한다. 

smart pointer는 객체에서 Reference count를 해서 더이상 참조하는 경우가 없으면 자동으로 obj를 Free시켜준다. 


1 아래와 같이 Smart pointer기본 개념은 아래와 같다.

class dog

{

public :

void bark() { printf("bark bark"); }

};


class sp { //dog객체를 위한 전용 smart pointer

dog* obj;

public :

~sp() { delete obj; }  //   scope를 벗어날때 자동으로   Destroy되도록 지원한다.

sp(dog* p = 0) : obj(p) {}  // 생성자 obj값을 초기화한다.

dog* operator->() { return obj; } // --> 연산자 재정의

dog& operator*() { return *obj; } // * 연산자 제정의

};


int main()

{

sp p = new dog;  // sp p( new dog); 와 같다.

p->bark();  // -> 연산자 재정의에 의해서 동작한다. 

(*p).bark(); // . 연산자 재정의가 필요하다.

    return 0;

}


2. sp class를 template으로 변환해 보자. 

template<typename T> class sp

{

T* obj;

public:

~sp() { delete obj; }  //   scope를 벗어날때 자동으로 메모리가 회수 되도록 한다.

sp(T* p = 0) : obj(p) {}  // 생성자 obj값을 초기화한다.

T* operator->() { return obj; } // --> 연산자 재정의

T& operator*() { return *obj; } // * 연산자 제정의

};


int main()

{

sp<dog> p = new dog;  // sp p( new dog); 와 같다.

p->bark();  // -> 연산자 재정의에 의해서 동작한다. 

(*p).bark(); // . 연산자 재정의가 필요하다.

    return 0;

}


3. 아래와 같이 포인터가 복사되면 문제가 발생한다. 어느한쪽이 자동으로 메모리를 회수하면 다른 포인터에서 참조할때 문제가 발생한다.

위를 위해서 복사될때 참조카운터를 증가시키고, 제거될때 참조카운터를 감소시키고 참조카운터가 0이 되면 메모리를 회수한다.

int main()

{

sp<int> p1 = new int;

*p1 = 10;

sp<int> p2 = p1;

return 0;

}


4. 참조계수 counter를 추가해 보자 

template<typename T> class sp

{

T* obj;

int *ref_count;

public:

~sp() { 

if (--(*ref_count) == 0) // 참조계수를 감소하고 0이되면 메모리를 회수한다.

{

delete obj;

delete ref_count;

}

delete obj; 

}  //   scope를 벗어날때 자동으로   Destroy되도록 지원한다.

sp(T* p = 0) : obj(p)  // 생성자 obj값을 초기화한다.

{

ref_count = new int; // 참조계수 값을 할당한다.

sp(const sp& p) : obj(p.obj);ref_count(p->ref_count) // 복사 생성자

{

++(*ref_count) // 복사 생성되면 참조계수 count를 증가한다.

}

T* operator->() { return obj; } // --> 연산자 재정의

T& operator*() { return *obj; } // * 연산자 제정의

};


int main()

{

sp<int> p1 = new int;

*p1 = 10;

sp<int> p2 = p1;

getchar();

return 0;

}


5. 4에 문제는 복사될때 마다 참조계수용 포인터 메모리가 증가한다. 메모리 사용에 문제가 있다. 

Smart pointer가 관리하는 객체에 참조계수를 넣어두자 그럼 메모리 사용문제가 발생하지 않는다. 

즉 참조계수를 관리하는 객체  Refbase를 만들고 이를 상속받아 객체를 만들어 해결하자. 


class RefBase // 참조계수(RefBase)를 관리하는 객체를 만든다.

{

int mCount;

public :

RefBase() : mCount(0) {}

virtual ~RefBase() {}

void inc_ref() { ++mCount; }

void dec_ref() { if (mCount == 0) delete this; }

};


class dog : public RefBase // smart pointer를 사용하는 객체는  RefBase 객체를 상속받아 사용한다.

{

public : 

~dog() { printf("bark bark"); }

};


template<typename T> class sp // smart pointer는 객체에만 있는 참조계수를 상황에 따르 증가 감소 시킨다.

{

T* obj;

public:

sp(T* p = 0) : obj(p) { obj->inc_ref(); }  // 생성자 obj값을 초기화한다.

sp(const sp& p) : obj(p.obj) {

obj->inc_ref();

}

~sp() { 

obj->dec_ref();

}

T* operator->() { return obj; } // --> 연산자 재정의

T& operator*() { return *obj; } // * 연산자 제정의

};


int main()
{
sp<dog> p1 = new dog;
sp<dog> p2 = p1;
return 0;
}

주의할것은 Refbase를 상속하지 않는경우에는 사용이 불가능하다는거. 

그래서 sp<int> p1 같은것은 사용이 불가능 합니다.


' Software > C++' 카테고리의 다른 글

C++ 스마트포인터 참조금지, 대입금지  (0) 2016.08.21
C++참조변수-2  (0) 2016.07.30
C++ 참조변수-1  (0) 2016.07.30