더북(TheBook)

shared_ptr<T>는 정의할 때 다른 shared_ptr<T>로 초기화할 수 있다.

std::shared_ptr<double> pdata2 {pdata};

pdata2pdata와 같은 변수를 가리킨다. 따라서 레퍼런스 카운트가 증가한다. shared_ptr<T>를 다른 shared_ptr<T>에 할당하는 것도 가능하다.

std::shared_ptr<double> pdata{ new double{ 999.0 } };
std::shared_ptr<double> pdata2;            // nullptr를 갖는 포인터
pdata2 = pdata;                            // 포인터 복제 - 둘 다 같은 변수를 가리킨다
std::cout << *pdata << std::endl;          // 999.0을 출력한다

물론, pdata를 복제하면 레퍼런스 카운트가 증가한다. 두 포인터가 모두 초기화(reset)되거나 소멸되어야 double 변수에 할당된 메모리가 해제된다. shared_ptr<T>는 기본적으로 자유 공간에 생성된 배열의 주소를 저장하는 용도로는 쓸 수 없다. 그러나 자유 공간에 생성한 array<T>vector<T> 컨테이너의 주소를 저장하는 건 가능하다.

Note ≣

배열을 가리키는 shared_ptr<T> 객체를 생성하는 것도 가능하다. 이렇게 하려면 스마트 포인터가 배열을 위한 힙 메모리를 해제하기 위해 사용하는 deleter 함수를 구현해야 한다. 이를 구현하는 방법은 이 책의 범위를 벗어난다.

unique_ptr<T>와 마찬가지로 shared_ptr<T>get() 멤버를 호출해서 shared_ptr<T>가 가리키는 객체의 원시 포인터를 얻을 수 있다. 앞 절에서 정의한 pdata에 다음과 같이 작성할 수 있다.

auto pvalue = pdata.get();        // pvalue는 double* 타입이고 999.0을 가리킨다

원시 포인터를 반드시 사용해야 할 때만 이렇게 해야 한다.

Caution

shared_ptr<T> 객체의 복제본(duplicate)은 복제 생성자나 복제 할당 생성자로만 만들 수 있다. 다른 포인터에서 get()으로 반환한 원시 포인터를 사용해서 shared_ptr<T>를 생성하는 건 정의되지 않은 행동(undefined behavior)이며 대부분은 프로그램 충돌을 뜻한다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.