std::shared_ptr initialization: make_shared<Foo>() vs shared_ptr<T>(new Foo) [duplicate]

走远了吗. 提交于 2019-11-27 03:17:50
Mike Seymour

Both examples are rather more verbose than necessary:

std::shared_ptr<int> p(new int);  // or '=shared_ptr<int>(new int)' if you insist
auto p = std::make_shared<int>(); // or 'std::shared_ptr<int> p' if you insist

What's the difference?

The main difference is that the first requires two memory allocations: one for the managed object (new int), and one for the reference count. make_shared should allocate a single block of memory, and create both in that.

Which one should I prefer and why?

You should usually use make_shared as it's more efficient. As noted in another answer, it also avoids any possibility of a memory leak, since you never have a raw pointer to the managed object.

However, as noted in the comments, it has a potential disadvantage that the memory won't be released when the object is destroyed, if there are still weak pointers preventing the shared count from being deleted.

From en.cppreference.com

In contrast, the declaration std::shared_ptr<T> p(new T(Args...)) performs at least two memory allocations, which may incur unnecessary overhead.

Moreover, f(shared_ptr<int>(new int(42)), g()) can lead to memory leak if g throws an exception. This problem doesn't exist if make_shared is used.

So I would recommend the make_shared approach if possible.

doc_ds

Be aware that make_shared limits you to using the default allocation/deallocation functions so if you want to have more control, make_shared is not an option. In other words, something like

std::shared_ptr<uint8_t>(p, [](uint8_t *p){ /*user code */}); 

is impossible using make_shared. One could use allocate_shared instead, but only the allocator can be specified, not a deleter. Sometimes one need to control allocation and deletion of the wrapped class.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!