There have been two answers already, but they give, I fear, an incomplete picture.
You may reuse the storage of an object, providing that you respect a few conditions:
- You need not use a dynamically allocated object, any object is fine.
- You should properly destroy the previous object, by calling its destructor (explicitly); failure to do so leads to undefined behavior if the destructor has side-effects (see §3.8/4)
- The object that you place should have the same dynamic type as the previous object (see §3.8/7)
Let us review them, starting with any object is fine:
struct Foo {
int hello;
int world;
};
void automatically_allocated() {
Foo foo;
foo.~Foo();
new (&foo) Foo{};
}
void dynamically_allocated() {
std::unique_ptr<Foo> foo(new Foo{});
foo->~Foo();
new (&*foo) Foo{};
}
Let use continue with destroy the previous object:
struct Bar {
int hello;
std::string world;
};
void UNDEFINED_BEHAVIOR() {
Bar bar;
new (&bar) Bar{}; // most likely scenario: leaks memory owned by bar.world
}
And finally with same dynamic type:
struct Base { virtual ~Base() {} };
struct Derived: Base { std::string world; };
struct Other: Base { int hello; }
void UNDEFINED_BEHAVIOR() {
Derived derived;
Base& b = derived;
b.~Base(); // fine
new (&b) Other{};
// Most likely here, calls "derived.~Derived()" on an object of type Other...
}