4 ms·
The author writes "this might be why there is std::make_shared", but that's not really why it exists. When you create a std::shared_ptr it needs to allocate mem
by eklitzke 5y ago
The author writes "this might be why there is std::make_shared", but that's not really why it exists. When you create a std::shared_ptr it needs to allocate memory for a control block structure (which tracks the reference count) as well as the memory for the object itself. If you write std::shared_ptr<Foo>(new Foo) this will result in two memory allocations, one for the Foo object and the other for the std::shared_ptr control block. If you write std::make_shared<Foo>() then a single allocation will happen which has enough space for both the control block and the Foo object, and then placement new is used to initialize the memory for both structures. So std::make_shared exists to reduce the number of memory allocations that are being made, not for the reason suggested here.
- asveikau 5y agoI think the idea that you are also relying on a presumably well tested library to get the exception corner cases right is also noteworthy. Memory leaks on allocation failure are pretty common in naive code, and a good thing to handle in a library where it can get well thought out.
- Koshkin 5y agoThis is very important. Try to hide most of complexity in a library, and then unit-test the hell out of it.
- haldean 5y agoThere's a crazy downside to make_shared that I learned recently because of this: if you have a weak pointer to a shared thing, and the refcount for the shared thing drops to zero, the weak pointers will keep the allocation for the object "alive", because they still need access to the remnant and the remnant was created in the same allocation as the object so they can't be freed separately. So now I only use make_shared if I know for sure there won't be a weak_ptr pointing at it (or if the base object has a relatively small memory footprint after it's been destructed).
- ot 5y agoYeah, that's definitely something to be aware of. It's usually not an issue as most objects have small footprint (and any allocations they in turn hold would be released when the strong refcount goes to 0).
- Asooka 5y agoWon't the object be destructed though? So while the memory for the object is kept, the memory for the object's heap-allocated members is not. I.e. if you have a 100mb string, after only weak references are left you won't have 100mb memory taken, but only sizeof(string) + sizeof(control block).
- nneonneo 5y agoDepends on the object. As OP notes, `make_shared` with weak pointers is fine "if the base object has a relatively small memory footprint after it's been destructed". There's lots of cases where the object itself is big, though. Think of objects with big fixed arrays, "god objects" with a bajillion pointers, or objects which themselves allocate data in-line.
- quietbritishjim 5y agoIt exists for both reasons. That's why there's also a std::make_unique even though it doesn't have a control block (although it was added later, but that was just an oversight).
- MaxBarraclough 5y ago> It exists for both reasons. I believe this is correct. Here's [0] some old Boost documentation on Boost's make_shared which inspired the C++ standard's make_shared. It mentions both reasons. [0] https://www.boost.org/doc/libs/1_67_0/libs/smart_ptr/doc/html/smart_ptr.html#make_shared https://www.boost.org/doc/libs/1_67_0/libs/smart_ptr/doc/htm...