Is it possible to force std::make_shared
to use a class's new operator? This relates to another SO question. According to that question, std::make_shared
uses a custom allocator:
From the standard (§20.7.2.2.6 shared_ptr creation ):
Effects: Allocates memory suitable for an object of type T and constructs an object in that memory via the placement new expression ::new (pv) T(std::forward(args)...).
As such, I thought that I could use a custom placement new operator, but that appears to be false
// std::cout
#include <iostream>
// std::make_shared
#include <memory>
// Track what we're making
struct Foo {
Foo() {
std::cout << "Foo constructor" << std::endl;
}
Foo(Foo const & foo) {
std::cout << "Foo copy constructor" << std::endl;
}
Foo(Foo && foo) {
std::cout << "Foo move constructor" << std::endl;
}
Foo & operator = (Foo const & foo) {
std::cout << "Foo copy assignment" << std::endl;
return *this;
}
Foo & operator = (Foo && foo) {
std::cout << "Foo move assignment" << std::endl;
return *this;
}
void * operator new(std::size_t size) throw(std::bad_alloc) {
std::cout << "Foo new" << std::endl;
return ::operator new(size);
}
void * operator new(std::size_t size, void * p) throw() {
std::cout << "Foo placement new" << std::endl;
return ::operator new(size,p);
}
void* operator new (std::size_t size, std::nothrow_t const & nothrow_value)
throw()
{
std::cout << "Foo nonthrowing new" << std::endl;
return ::operator new(size,nothrow_value);
}
void operator delete(void * p, std::size_t size) {
std::cout << "Foo delete" << std::endl;
::operator delete(p);
}
~Foo() {
std::cout << "Foo destructor" << std::endl;
}
};
int main() {
std::cout << "---Creating foo" << std::endl;
auto foo = std::make_shared <Foo> ();
std::cout << "---Creating foo2" << std::endl;
auto foo2 = std::shared_ptr <Foo> (new Foo());
std::cout << "---Creating foo3" << std::endl;
auto foo3 = std::allocate_shared <Foo> (std::allocator <Foo>());
std::cout << "---fin" << std::endl;
}
which gives
---Creating foo
Foo constructor
---Creating foo2
Foo new
Foo constructor
---Creating foo3
Foo constructor
---fin
Foo destructor
Foo destructor
Foo delete
Foo destructor
Also tucked in there was an attempt to force an allocator that would call the custom new operator with the call to std::allocate_shared
. In any case, is there a way to make std::make_shared
call the custom new operators without defining a whole new allocator?
No, this is not possible (with make_shared
).
Since a custom allocator for class T
will typically be written and optimized (for example with a pool) to expect allocations of size T
, and make_shared
will be allocating more memory than that, I imagine it wasn't deemed an important feature to support.
Further, the standard provides allocate_shared
for the case where you wish to use a custom allocator.
Sort of.
What you do instead is create a structure containing aligned storage with a custom destroyer that cleans up the object and a bool saying if you should do so.
Then placement new the aligned storage.
Now use the aliasing shared ptr constructor to return a pointer to the aligned storage as a different type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With