원문: http://www2.research.att.com/~bs/C++0xFAQ.html#std-shared_ptr
shared_ptr은 공유 소유권을 표현하기 위해 사용된다. 즉, 코드 두 조각이 어떤 데이터에 접근하는 게 필요하지만 어느 쪽도 배타적인(객체를 소멸시키는 책임을 가졌다는 의미의) 소유권을 가지지 않는 경우에 사용된다. shared_ptr은 객체의 사용 횟수가 0이 될 때 그 포인터가 가리키는 객체가 삭제되는 counted pointer의 한 종류이다. 여기 매우 인공적인 예제가 있다.
void test()
{
shared_ptr p1(new int); // count is 1
{
shared_ptr p2(p1); // count is 2
{
shared_ptr p3(p1); // count is 3
} // count goes back down to 2
} // count goes back down to 1
} // here the count goes to 0 and the int is deleted.
더 현실적인 예제는 일반적인 그래프의 노드를 가리키는 포인터가 될 것이다. 그 그래프에서 어떤 노드를 가리키는 포인터를 제거하려고 기다리고 있는 누군가가 있는데, 그 노드를 가리키는 포인터를 다른 누군가가 잡고 있는지를 모르는 상황인 것이다. 어떤 노드가 소멸자에 의한 액션을 필요로 하는 자원(예를 들어, 노드가 삭제될 때 파일이 닫혀야 하는 파일 핸들)을 가지고 있을 수 있다면 말이다. 아마도 절약하려고 하는 자원에서 쓰레기가 충분히 생기지 않거나, 실행 환경이 허락하지 않거나, 관리되는 리소스가 그저 메모리가 아닌(예를 들어 파일 핸들) 경우를 제외하고는, 뭔가를 위해 가비지 컬렉터를 끼워넣으려고 한다면 shared_ptr을 고려해볼 수 있을 것이다.
예를 들자면,
struct Node { // 주의: 하나의 Node는 여러 다른 노드로부터 참조될 수 있다.
shared_ptr left;
shared_ptr right;
File_handle f;
// ...
};
여기서 Node 구조체의 소멸자(암시적으로 생성된 소멸자가 잘 할 것이다)가 그 하위 노드들을 삭제한다. 즉, 멤버 변수 left와 right의 소멸자가 호출된다. left가 shared_ptr이기 때문에, left가 노드를 가리키는 마지막 포인터라면 그 Node는 (만약 존재한다면) 삭제된다. right는 비슷하게 다뤄지고, f의 소멸자는 f를 위해 필요한 뭔가를 하게 된다.
하나의 소유자로부터 다른 소유자로 포인터를 넘기는 것만을 위해서라면 shared_ptr을 사용하지 않는 게 좋겠다는 점을 유념하라. 다시 말해, 그건 (번역) unique_ptr이 필요한 경우이고 unique_ptr은 더 싸고 더 잘 한다. 만약 factory function이나 비슷한 것으로부터의 리턴 값으로서 counted pointer를 사용해왔다면, shared_ptr 대신에 unique_ptr로 업그레이드하는 것을 고려해봐라.
제발 메모리 누수를 방지하기 위한 시도로 생각없이 포인터를 shared_ptr로 바꾸지 마라. shared_ptr은 만병통치약도 아니고 비용이 안 드는 것도 아니다.
shared_ptr은 공유된 소유권을 표현하지만 공유된 소유권은 나의 이상은 아니다. 객체가 명확한 소유자와 명확하고 예측가능한 수명을 가지는 게 좋겠다.