8

I tried looking for an answer, but couldn't find anything helpful to understand what happens behind the scenes.

Assuming that we have the following:

class Base
{
public:
    virtual int request() = 0; 
    void* operator new(long unsigned int size) = delete;
};


class Derived final : public Base
{
public:
    int request() override;
};

int Derived::request()
{
    return 2;
}

On the base class I have deleted the new operator because I don't want to be able to create pointers. I know it might not make any sense, it is just an experiment.

When I call g++ gives me a compilation error to tell me that the new operator is deleted. Exactly what I expected.

int main()
{
    auto d =  std::make_unique<Derived>();
    int value = d->request();
    std::cout << "Request value is " << value << "." << std::endl;

    return 0;
}

But if I create a shared_ptr the code compiles and runs fine.

    auto d =  std::make_shared<Derived>();

Why is this code valid when creating shared pointers. The operator is not being used in this case?

  • 3
    Probably because `std::make_unique` does not use the class's new operator (which was deleted). It uses an in-place constructor (placement new). – Eljay Dec 03 '18 at 13:08
  • 1
    BTW: you can't prevent in 100% from creating pointers. One can always create a class that aggregates yours and put it on heap just like that. – Michał Łoś Dec 03 '18 at 16:07

1 Answers1

11

std::make_shared use global placement new version of the operator new, by std::allocator::construct

It is necessary to store object and atomic reference counter in the same block of memory, so that shared_ptr template works almost equal to intrusive smart pointer.

You can not prevent std::make_shared to construct a smart pointer.

Victor Gubin
  • 2,782
  • 10
  • 24
  • 2
    `make_shared` should be using the reserved global placement allocation function. Not doing so would be a bug in the implementation. Attempting to delete that function (in global scope) is undefined behavior. – T.C. Dec 05 '18 at 08:53