2015년 1월 16일 금요일

[미완] [C/C++] 스마트 포인터( new > auto_ptr > shared_ptr)

[미완] [C/C++] 스마트 포인터( new > auto_ptr > shared_ptr)

#include <iostream>
using namespace std;

#include <memory> // auto_ptr, shared_ptr

class CTest {
public:
CTest() { cout << "CTest()" << endl; };
~CTest() { cout << "~CTest()" << endl; };
};

void New( void )
{
cout << "New() ----------------" << endl;
CTest* p = new CTest;
// delete p;
}

void AutoPtr( void )
{
cout << "AutoPtr() ----------------" << endl;
std::auto_ptr<CTest> p(new CTest);
}

void SharedPtr( void )
{
cout << "SharedPtr() ----------------" << endl;
std::tr1::shared_ptr<CTest> p (new CTest);
}

int main()
{
New();

AutoPtr();

SharedPtr();
}

1. new
당연히 delete를 해야하지만 인간이지라 함수 중간에 return을 만날수도 있고 try-catch에 걸리수도 있고 해서 delete를 못하면 메모리누수가 발생한다. New()함수

2. auto_ptr
그래서 나온게 auto_ptr이다. 소멸자에 객체해제가 있었서 사용자가 delete를 신경 안써도 된다. AutoPtr() 함수
하지만 문제점 발생: auto_ptr은 소유권개념이 있다.

std::auto_ptr<int> p1(new int(10)); // p1=10
std::auto_ptr<int> p2(p1);            // p2=10, p1=null

//cout << *p1 << endl; // 에러발생
cout << *p2 << endl; // 10출력

p2가 p1을 복사하는 순간 new int(10)의 소유권이 p2에게 넘어가서
p1은 null이고 p2가 new int(10)을 가리킨다.

이로 인해서 STL컨테이너에서는 사용하면 안된다.
(C++11부터 사용 중지권고했고 C++17부터는 제거 돼었다고 합니다.)

3. shared_ptr
그래서 나온게 shared_ptr이다. 참조 카운팅이 추가되었다.

std::tr1::shared_ptr<int> p1(new int(10)); // 참조 카운팅=1
std::tr1::shared_ptr<int> p2(p1);            // 참조 카운팅=2

cout << *p1 << endl; // 10출력
cout << *p2 << endl; // 10출력

p2가 p1를 복사하는 순간 참조 카운팅은 2가 된다.
이 참조 카운팅이 0이 되는 순간에 delete를 한다.

하지만 문제점 발생
배열을 delete[]하지 않는다.

std::tr1::shared_ptr<CTest> p (new CTest[10]); // 생성자 10번 호출하지만 소멸자는 1번만 호출
이처럼 배열을 할당하면 소멸시 문제가 발생한다.

여러해결책이 있는데
배열대신 Vector를 사용하라고 한다.

std::vector<std::tr1::shared_ptr<CTest>> p(10); // 벡터 생성

std::tr1::shared_ptr<CTest> p1(new CTest); // 생성자 호출
std::tr1::shared_ptr<CTest> p2(new CTest); // 생성자 호출
// 2번 생성했으므로 소멸자 2번 호출함

댓글 없음:

댓글 쓰기