Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

갱스

make_shared의 장단점 본문

카테고리 없음

make_shared의 장단점

pknam 2017. 12. 17. 22:22

shared_ptr로 관리되는 객체를 생성하는 방법은 두가지가 있다

1. shared_ptr<Object>(new Object)

2. make_shared<Object>()


이 두가지 방식에 차이점이 있을까? 있다면 어느 방식이 더 좋을까?

아래 링크는 이 의문에 대한 좋은 답변이다

https://stackoverflow.com/questions/20895648/difference-in-make-shared-and-normal-shared-ptr-in-c


답변을 간략히 정리해보았다



1. 메모리할당 (heap allocation) 횟수가 다르다

shared_ptr<Object>(new Object)를 쓰면 Object 객체를 생성할 때 한번, reference count 관리를 위한 control block을 생성할 때 한번. 총 두번 메모리 할당이 발생한다. 물론 해제도 두번 발생한다.

반면 make_shared<Object>()를 쓰면 Object객체를 위한 메모리와 control block을 위한 메모리를 한번에 할당받는다. 해제도 한번에 된다.


make_shared를 쓰면 메모리할당 횟수를 줄이는 성능상 이점이 있지만, Object가 해제되어도 되는 상황임에도 해제되지 않는 상황이 생길 수 있다.

이는 control block이 shared_ptr의 ref-count와 weak_ptr의 ref-count를 구분해서 관리하기 때문인데, shared_ptr의 ref-count가 0이 되어도 weak_ptr의 ref-count는 0이 되지 않을 수 있다. 따라서 둘 다 0가 되지 않는 한 control block은 valid하기 때문에 Obect도 덩달아 해제되지 못한다.


2. make_shared는 예외에 안전하다

위 링크의 코드를 가져와서 설명하자면 이렇다

F(std::shared_ptr<Lhs>(new Lhs("foo")),
  std::shared_ptr<Rhs>(new Rhs("bar")));

이렇게 F라는 함수를 호출한다고 치자. C++은 이 한 라인을 임의의 순서대로 평가하는 것을 허용한다. 그래서 컴파일러마다 실행순서를 다르게 해석할 수 있다. 예를 들어 어떤 컴파일러는 아래와 같은 순서로 위 코드를 해석할 수 있다. 

 * new Lhs

 * new Rhs

 * std::shared_ptr<Lhs>()

 * std::shared_ptr<Rhs>()


이 때 new Rhs 구문에서 예외가 발생했다면 Lhs 객체는 영원히 해제되지 않을 것이다. 이렇게 컴파일러에 따라 문제가 생길수도 있고 생기지 않을 수도 있는 코드를 작성하는 것은 분명 바람직하지 않다.


따라서 위 코드는 아래와 같이 make_shared를 쓰는 것이 더 좋다

F(std::make_shared<Lhs>("foo"), std::make_shared<Rhs>("bar"));



Comments