Suppose I have a code like this:
class Foo
{
private:
int x;
public:
void* operator new(size_t size);
void operator delete(void* p);
};
int main() {
auto ptr = std::shared_ptr<Foo>(new Foo());
return 0;
}
The shared_ptr
will create separate control-block and object-block. I suppose the memory for the object block will be created using the Foo::operator new()
. Is the memory for the control-block created using ::operator new()
or Foo::operator new()
? And in case of make_shared
, would the entire single-block of memory be allocated using Foo::operator new()
?
The shared_ptr will create separate control-block and object-block. I suppose the memory for the object block will be created using the Foo::operator new().
Nope. You already passed in the pointer to the object, so it only needs a control block. In fact, I believe no shared_ptr construction allocates a single object-block, they never need it.
Is the memory for the control-block created using ::operator new() or Foo::operator new()?
C++ spec doesn't specify, but the sane thing for an implementation to do is rebind the allocator to an Allocator<ControlBlock>
and use its allocate
member, which will almost certainly use ::operator new()
. It's allocating a ControlBlock
, not a Foo
.
And in case of make_shared, would the entire single-block of memory be allocated using Foo::operator new()?
The C++ spec does specify this one:
3.11.3.6 ... The allocate_shared templates use a copy of a (rebound for an unspecified value_type) to allocate memory...
7 Remarks: (7.1) — Implementations should perform no more than one memory allocation. [ Note: This provides efficiency equivalent to an intrusive smart pointer. — end note ]>
In this case, the implementation will rebind the allocator to an Allocator<ControlAndObjectBlock>
and use its allocate
member, which will almost certainly again use ::operator new()
, since it's allocating a ControlAndObjectBlock
instead of a Foo
.
summary: Since shared_ptr never actually allocates an object block by itself, it'll never use Foo::operator new
. However, your std::shared_ptr<Foo>(new Foo())
expression allocates a Foo
using Foo::operator new
, and then constructs a std::shared_ptr<Foo>
from that pointer.