본문 바로가기

개발

Modern C++ 스마트 포인터

스마트 포인터의 필요성이야 말할 것도 없지만, 그 동안 STL에서 제대로된 스마트 포인터를 지원 해 주지 않아서 대부분 외부 라이브러리를 쓰거나 Boost의 그것을 쓰곤 했다. 그런데 C++ 11, 14를 거쳐 자체 스마트 포인터를 써도 되지 않을까 하는 수준에 이르렀기에 기대가 크다.


 지금 부터는 Effective Modern C++ 에서 발췌한 스마트 포인터에 관한 정리다.


 Raw Point (날 포인터)를 사랑 하기 힘든 이유.

 - 선언만 봐서는 하나의 객체를 가리키는지 배열을 가리키는지 구분할 수 없다.

 - 선언만 봐서는 포인터를 다 사용한 후 포인터가 가리키는 객체를 독자가 직접 파괴해야 하는지 알 수 없다.

 - 구체적으로 어떻게 파괴해야하는지에 대한 정보를 얻을 수 없다.

 - delete를 이용해서 파괴해야 함을 알게 된다고 해도, 첫번째 이유 때문에 delete를 사용해야 할지 아니면 delete[]를 사용해야 할지 않 수 없는 경우가 있다.

 - 코드의 모든 경로에서 파괴가 정확히 한 번 일어남을 보장하기 어렵다.

 - 포인터가 피지칭 객체를 잃었는지를 알아내는 방법은 없다.


 이런 문제점들을 해결하는 방법으로 스마트 포인터를 사용한다.


 0. std::unique_ptr은 std::auto_ptr이 할 수 있는 모든 것을 더 나은 방식으로 해낸다. 따라서 코드에서 모든 std::auto_ptr을 std::unique_ptr로 대체한 후 std::auto_ptr에 대해서는 완전히 잊는 것이 좋다.


 1. 소유권 독점 자원의 관리에는 std::unique_ptr을 사용하라.

 : std::unique_ptr는 독점적 소유권 의미론을 체현하고 있다. 널이 아닌 std::unique_ptr는 항상 자신이 가리키는 객체를 소유한다. std::unique_ptr를 이동하면 소유권이 원본 포인터에서 대상 포인터로 옮겨진다. (원본 포인터는 널로 설정된다.) std::unique_ptr의 복사는 허용되지 않는데, 만일 std::unique_ptr을 복사할 수 있다면, 두 std::unique_ptr가 같은 자원을 가리킬 뿐만 아니라 두 포인터 모두 사진이 그 자원을 소유하고 있다고 생각하는 상황이 빚어질 것이기 때문이다. 그런 의미에서 std::unique_ptr은 이동 전용 형식이다.

 : 기본적으로 자원파괴는 delete를 통해 일어나나, 커스텀 삭제자를 지정할 수도 있다.

 : std::unique_ptr을 std::shared_ptr로 손쉽게 변환할 수 있다.


 2. 소유권 공유 자원의 관리에는 std::shared_ptr을 사용하라.

 : 모든 std::shared_ptr는 객체가 더 이상 필요하지 않게 된 시점에서 객체가 파괴됨을 보장하기 위해 협동한다. 객체를 가리키던 마지막 std::shared_ptr이 객체를 더 이상 가리키지 않게 되면 (이를테면 그 std::shared_ptr이 다른 객체를 가리키게 되었거나 자신이 파괴되는 시점이어서), 그 std::shared_ptr은 자신이 가리키는 객체를 파괴한다. 

 : std::shared_ptr은 자신이 객체를 가리키는 최후의 공유 포인터임을 참조 횟수 (reference count)를 통해 안다.

 : std::shared_ptr의 크기는 날 포인터의 두 배이다.

 : 참조 횟수를 담을 메모리를 반드시 동적으로 할당해야 한다.

 : 참조 횟수의 증가와 감소가 반드시 원자적(atomic) 연산이어야 한다.

 : std::shared_ptr 생성자에 날 포인터를 넘겨주는 일은 피하라

 : std::shared_ptr 생성자를 날 포인터로 호출할 수 밖에 없는 상황이라면 날 포인터 변수를 거치지 말고 new의 결과를 직접 전달 하라. std::shared_ptr<Widget> spw1(new Widget, loggingDel);

 

 3. std::shared_ptr처럼 작동하되 대상을 잃을 수도 있는 포인터가 필요하면 std::weak_ptr을 사용하라.

 : std::weak_ptr은 자신을 생성하는 데 쓰인 std::shared_ptr이 가리키는 것과 동일한 객체를 가리키나, 그 객체의 참조 횟수에는 영향을 주지 않는다.


 4. new를 직접 사용하는 것보다 std::make_unique와 std::make_shared를 선호하라.

 : new의 직접 사용에 비해 make함수를 사용하면 소스 코드 중복의 여지가 없어지고, 예외 안전성이 향상되고, std::make_shared와 std::allocate_shared의 경우 더 작고 빠른 코드가 산출된다.


[출처] Modern C++ 스마트 포인터|작성자 밤비

http://blog.naver.com/vambii/220597089238

'개발' 카테고리의 다른 글

전문가를 위한 C++ 책을 읽고 몇 가지 정리  (0) 2016.02.15
Modern C++ auto에 관해서  (0) 2016.02.15
Full Stack Engineer에 대하여  (0) 2015.11.30
Mysql Join 해부(Left, Right, Outer, Inner Join)  (0) 2015.11.30
RnR  (0) 2015.11.30