Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it well-defined/legal to placement-new multiple times at the same address?

(Note: this question was motivated by trying to come up with preprocessor hackery to generate a no-op allocation to answer this other question:

Macro that accept new object

...so bear that in mind!)

Here's a contrived class:

class foo {
private:
    int bar;
public:
    foo(int bar) : bar (bar)
        { std::cout << "construct foo #" << bar << std::endl; }
    ~foo()
        { std::cout << "destruct foo #" << bar << std::endl; }
};

...which I will allocate like this:

// Note: for alignment, don't use char* buffer with new char[sizeof(foo)] !
void* buffer = operator new(sizeof(foo));

foo* p1 = new (buffer) foo(1);
foo* p2 = new (buffer) foo(2);

/* p1->~foo(); */ /* not necessary per spec and problematic in gen. case */
p2->~foo();

On the gcc I've got around, I get the "expected" result:

construct foo #1
construct foo #2
destruct foo #2

Which is great, but could the compiler/runtime reject this as an abuse and still be on the right side of the spec?

How about with threading? If we don't actually care about the contents of this class (let's say it's just a dummy object anyway) will it at least not crash, such as in the even simpler application which motivated this with a POD int?

like image 744
HostileFork says dont trust SE Avatar asked Sep 23 '11 04:09

HostileFork says dont trust SE


People also ask

Does placement New allocate?

Because placement new does not allocate memory, you should not use delete to deallocate objects created with the placement syntax.

In which cases we would need to use placement new?

Use cases. Placement new is used when you do not want operator new to allocate memory (you have pre-allocated it and you want to place the object there), but you do want the object to be constructed.


1 Answers

Peforming placement-new several times on the same block of memory is perfectly fine. Moreover, however strange it might sound, you are not even requred to destruct the object that already resides in that memory (if any). The standard explicitly allows that in 3.8/4

4 A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released;[...]

In other words, it is your responsibility to take into account the consequences of not calling the destructor for some object.

However, calling the destructor on the same object twice as you do in your code is not allowed. Once you created the second object in the same region of memory, you effectively ended the lifetime of the first object (even though you never called its destructor). Now you only need to destruct the second object.

like image 86
AnT Avatar answered Oct 13 '22 00:10

AnT