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; } // * 연산자 제정의
};
주의할것은 Refbase를 상속하지 않는경우에는 사용이 불가능하다는거.
그래서 sp<int> p1 같은것은 사용이 불가능 합니다.
' Software > C++' 카테고리의 다른 글
C++ 스마트포인터 참조금지, 대입금지 (0) | 2016.08.21 |
---|---|
C++참조변수-2 (0) | 2016.07.30 |
C++ 참조변수-1 (0) | 2016.07.30 |