Search code examples
c++new-operatordelete-operatornew-expression

If I call operator new directly without a new expression and cast the return pointer type safe?


Hello I am on chapter 19 from C++ primer 5th edition. 'Operator new and delete vs new and delete expression and placement new':

AFAIK operator new and operator delete allocate and deallocate memory respectively but don't construct an object there. On the other hand a new-expressioncalls operator new to allocate memory, construct an object in that memory address and finally returns a pointer to the newly allocated and initialized object.

So for the understanding sake I've tried this:

struct Foo{
    Foo(){std::cout << "Foo()\n";}
    ~Foo(){std::cout << "~Foo()\n";}
    void bar() const{
        std::cout << "Foo::bar()\n";
    }
};

int main(){


    Foo* pf = (Foo*)operator new(sizeof(Foo)); // Foo() is not called! Is it UB?
    pf->bar(); // looks to work fine. Does it really?
    delete pf; // looks fine?


    Foo* pf2 = new Foo{}; // ok Foo() is called 
    pf2->bar(); // OK
    delete pf2; // OK ~Foo() is called

}

As you can see in the first example I've called operator new directly, and I guess this latter does allocate memory only but doesn't construct an object there and finally it returns a pointer to void pointing to the newly allocated member.

So I don't get the constructor called Foo(). Now why calling a member function works fine? pf->bar()? or does this yield an undefined behavior?

The second example (pf2) is straightforward.

  • If one is safe and correct, what happened? how could I use an uninitialized object? Thank you!

Solution

  • Unless you use placement new (which is basically the other half of the ordinary new), no Foo object exists, so you can't call a member function on it. Moreover, if you do use placement new, you must call the destructor yourself:

    Foo* pf = new (operator new(sizeof(Foo))) Foo;  // no cast needed
    pf->bar();
    pf->~Foo();
    operator delete(pf);  // analogous, though not equivalent, to std::free