What happens when using make_shared

后端 未结 3 420
[愿得一人]
[愿得一人] 2020-12-14 01:20

I\'m interested if these two lines of code are the same:

shared_ptr sp(new int(1)); // double allocation?
shared_ptr sp(make_shared<         


        
相关标签:
3条回答
  • 2020-12-14 02:04

    Explanation from cppreference std::shared_ptr in Implementation notes section

    In a typical implementation, std::shared_ptr holds only two pointers:

    1. a pointer to the managed object
    2. a pointer to control block

    When shared_ptr is created by calling std::make_shared or std::allocate_shared, the memory for both the control block and the managed object is created with a single allocation. The managed object is constructed in-place in a data member of the control block. When shared_ptr is created via one of the shared_ptr constructors, the managed object and the control block must be allocated separately. In this case, the control block stores a pointer to the managed object.

    0 讨论(0)
  • 2020-12-14 02:15

    The first case does not perform a double allocation, it performs two allocations, one for the managed object and one for the control block of the shared_ptr.

    For the second case, cppreference has a good explanation for why std::make_shared usually only performs one memory allocation it says (emphasis mine going forward):

    This function typically allocates memory for the T object and for the shared_ptr's control block with a single memory allocation (it is a non-binding requirement in the Standard). In contrast, the declaration std::shared_ptr p(new T(Args...)) performs at least two memory allocations, which may incur unnecessary overhead.

    and from std::shared_ptr section it says:

    When shared_ptr is created by calling std::make_shared or std::allocate_shared, the memory for both the control block and the managed object is created with a single allocation. The managed object is constructed in-place in a data member of the control block. When shared_ptr is created via one of the shared_ptr constructors, the managed object and the control block must be allocated separately. In this case, the control block stores a pointer to the managed object.

    This make_shared description is consistent with the C++11 draft standard which says in section 20.7.2.2.6 shared_ptr creation

    template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
    template<class T, class A, class... Args>
      shared_ptr<T> allocate_shared(const A& a, Args&&... args);
    

    [...]

    Remarks: Implementations should perform no more than one memory allocation. [ Note: This provides efficiency equivalent to an intrusive smart pointer. —end note ]

    [ Note: These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as the reference counts. —end note ]

    Herb Sutter has a more detailed explanation of the advantages of using make_shared in GotW #89 Solution: Smart Pointers and points out some advantages:

    • It reduces allocation overhead
    • It improves locality.
    • Avoids an explicit new.
    • Avoids an exception safety issue.

    Be aware that when using std::weak_ptr using make_shared has some disadvantages.

    0 讨论(0)
  • 2020-12-14 02:16

    There is also a potential subtle bug: in sp(new int) you fist allocate an int (whose pointer is given to sp), than sp itself has to allocate a control block (will contain the counters and the deleter).

    Now, if doing this last allocation sp fails (low memory) you are left with a heap allocated int whose pointer is not held by anyone, and thus impossible to delete. (memory leak).

    0 讨论(0)
提交回复
热议问题