First, [basic.life]/8
clearly states that any pointers or references to the original foo
shall refer to the new object you construct at foo
in your case. In addition, the name foo
will refer to the new object constructed there (also [basic.life]/8
).
Second, you must ensure that there is an object of the original type the storage used for foo
before exiting its scope; so if anything throws, you must catch it and terminate your program ([basic.life]/9
).
Overall, this idea is often tempting, but almost always a horrible idea.
(8) If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
- (8.1) the storage for the new object exactly overlays the storage location which the original object occupied, and
- (8.2) the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
- (8.3) the type of the original object is not const-qualified, and, if a class type, does not contain any non-static
data member whose type is const-qualified or a reference type, and
- (8.4) the original object was a most derived object (1.8) of type
T and the new object is a most derived
object of type T (that is, they are not base class subobjects).
(9) If a program ends the lifetime of an object of type T with static (3.7.1), thread (3.7.2), or automatic (3.7.3) storage duration and if T has a non-trivial destructor, the program must ensure that an object of the
original type occupies that same storage location when the implicit destructor call takes place; otherwise the behavior of the program is undefined. This is true even if the block is exited with an exception.
There are reasons to manually run destructors and do placement new. Something as simple as operator=
is not one of them, unless you are writing your own variant/any/vector or similar type.
If you really, really want to reassign an object, find a std::optional
implementation, and create/destroy objects using that; it is careful, and you almost certainly won't be careful enough.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…