프로그래밍 언어/C/C++

[C++11] std::enable_shared_from_this

소혼 2018. 2. 6. 11:01
반응형

std::shared_ptr은 std::unique_ptr과 함께 C++11부터 사용 가능한 smart pointer 이다. 

std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer.
(
http://en.cppreference.com/w/cpp/memory/shared_ptr)

std::unique_ptr과 다른점은 ownership을 공유(shared)한다는 점이다.

std::shared_ptr 객체를 만들때 한가지 문제가 되는 부분이 있는데, 아래와 같은 상황이 발생하지 않도록 주의해야 한다는 점이다.

Bad* p = new Bad;

std::shared_ptr<Bad> a1(p);

std::shared_ptr<Bad> a2(p); // ERROR! you may want to write std::shared_ptr<Bad> a2(a1)

a1과 a2는 (같은 raw pointer p를 갖는) 서로 다른  스마트 포인터이기 때문에 위 코드는 런타임에 아래처럼 죽게 된다. (mac clang-900.0.39.2)

./a.out 

a.out(16448,0x7fff8e2d2340) malloc: *** error for object 0x7fc73b400340: pointer being freed was not allocated

*** set a breakpoint in malloc_error_break to debug

Abort trap: 6

우리가 raw pointer 를 아예 안쓰면 모르지만, 아래와 같은 경우는 난감하다.

void func(BadOrGood* p) {

  std::shared_ptr<BadOrGood> a(p);

  ...

}

T 를 구현할 때 std::enable_shared_from_this<T> 를 상속하면 T의 객체가 자신의 shared_ptr 객체를 알 수 있게 해준다.

class Good : public std::enable_shared_from_this<Good> { ... };

std::shared_ptr<Good> a(p.shared_from_this());

이렇게 enable_shared_from_this 를 상속받고, shared_ptr에 raw pointer를 넣을때는 shared_from_this() 를 통해 shared_ptr을 얻어서 호출하면 안전하다.

사실 아직 문제가 있는데

shared_ptr 객체를 만들지 않고  shared_from_this()를 호출하면 std::bad_weak_ptr exception이 발생한다.(C++17부터, 그전에는 undefined behavior)

그리고, 여전히 첫번째 예제(Bad)처럼 실수하면 죽는다.

이를 막기 위해서, 직접 new 를 못하게 막아 두고 shared_ptr 객체가 생성되도록 해야 한다.

class Good : public std::enable_shared_from_this<Good> {

public:

  std::shared_ptr<Good> create() { return std::make_shared<Good>();};

private:

  Good() = default;

};


반응형

'프로그래밍 언어 > C/C++' 카테고리의 다른 글

[C++] 소스코드에서 컴파일러 구분하기?  (0) 2021.01.19
[읽은 글] const correctness  (0) 2016.10.18
[C++11] std::function의 성능  (0) 2015.05.29
GCC options  (0) 2013.12.05
[C++11] Range based for loop  (4) 2013.11.13