Regarding the book "Effective Modern C++" from Scot Meyers, and the 21st item: "Prefer std::make_unique and std::make_shared to direct use of new":
"Some classes define their own versions of operator new and operator delete. Often, class-specific routines are designed only to allocate and deallocate chunks of memory of precisely the size of objects of the class. Such routines are a poor fit for std::shared_ptr’s support for custom allocation (via std::allocate_shared) and deallocation (via custom deleters), because the amount of memory that std::allocate_shared requests isn’t the size of the dynamically allocated object, it’s the size of that object plus the size of a control block. Consequently, using make functions to create objects of types with class-specific versions of operator new and operator delete is typically a poor idea."
Why is this a problem for allocate_shared/make_shared, if custom new and delete are called on same places as standard new and delete?
Construction:
Operator new is used just to construct the resource object, but make_shared/allocate_shared construct the constrol block.
Destruction:
With or without a custom deleter function specified, when delete is called, just the resource object should be removed. Cntrol block depends on reference and weak counts.
Why then the sentence: "Such routines are a poor fit for std::shared_ptr’s support for custom allocation (via std::allocate_shared) and deallocation (via custom deleters), because the amount of memory that std::allocate_shared requests isn’t the size of the dynamically allocated object, it’s the size of that object plus the size of a control block."?
std::make_uniqueis fine, since it doesn't need any extra data (in general case).Problem is
std::make_shared. To makestd::shared_ptrwork some extra data are needed: strong reference counter, weak reference counter, deleter function pointer.This means that when you do:
std::shared_ptr<Foo>{raw_pointer},std::shared_ptrwill allocate own buffer to keep this data. Now allocation is quite expensive sostd::make_sharedwas introduced to optimize use of heap. It allocates memory which will holdshared_ptrdata and pointed item side by side in single chunk of memory. It constructs pointed object in place.So when you have custom operator
newfor some class,std::make_sharedwill not use it. On other head if you pass raw pointer tostd::shared_ptrthen you will have two blocks of memory.