본문 바로가기

C++

[C++] 스마트 포인터 - shared_ptr과 unique_ptr

shared_ptr은 기존의 auto_ptr과 달리 포인팅 횟수를 계산하여 0이 되면 대상을 삭제한다. auto_ptr은 한 객체에 두 개의 포인터로 포인팅 하면(얕은 복사) 하나는 소멸되었다. 그러나 shared_ptr은 한 객체에 두 개의 포인터로 포인팅 하면 포인팅 카운트 값은 2이다. 하나의 포인터가 소멸하더라도 카운트 값이 1 감소하지만 대상 객체는 소멸하지 않는다.

 

 

shared_ptr 배열 삭제 예)

 

#include <iostream>
using namespace std;

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

void removeClass(myClass* ptr)
{
	cout << "RemoveClass()" << endl;

	//대상을 배열로 삭제
	delete[] ptr;
}

int main()
{
	cout << "main() start" << endl;

	//대상 객체를 소멸할 함수를 별도로 등록
	shared_ptr<myClass> ptr(new myClass[3], removeClass);
	cout << "main() end" << endl;

	return 0;
}

 

결과값:

main() start
myClass()
myClass()
myClass()
main() end
RemoveClass()
~myClass()
~myClass()
~myClass()

 

main() 함수 실행 후 3개의 배열이 생성되었고 main() 함수가 끝나자 3개의 배열 모두 정상적으로 소멸되었음을 확인할 수 있다.

 


unique_ptr은 shared_ptr과 유사하다고 볼 수 있다. 그러나 shared_ptr과 달리 한 대상을 오로지 한 포인터만 포인팅 할 수 있다.

 

#include <iostream>
using namespace std;

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

void removeClass(myClass* ptr)
{
	cout << "RemoveClass()" << endl;

	//대상을 배열로 삭제
	delete[] ptr;
}

int main()
{
	unique_ptr<myClass> ptr(new myClass);

	//에러
	//unique_ptr<myClass> new_ptr(ptr);
	//new_ptr = ptr;

	return 0;
}

 

따라서, new_ptr = ptr과 같은 코드는 모두 에러가 발생한다. 즉, 애초에 여러 포인터가 동시에 하나의 대상을 가리키는 일이 없도록 차단한다. 얕은 복사가 발생할 가능성을 차단한다는 의미이다.