This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[Accepted as a DR at the June, 2023 meeting.]
Subclause 6.7.4 [basic.life] bullet 1.5 specifies:
The lifetime of an object o of type T ends when:
- if T is a non-class type, the object is destroyed, or
- if T is a class type, the destructor call starts, or
- the storage which the object occupies is released, or is reused by an object that is not nested within o (6.7.2 [intro.object]).
Consider the expression new (p) T(x). Does the lifetime of *p end when p is returned from the allocation function, before x is evaluated? Or does the lifetime end when the constructor body starts executing, after x is evaluated?
The second option is conceivable for initialization by constructor and non-class types; for aggregate initialization, the first option must be used, because evaluation of x directly initializes a part of the resulting object. The first option is simpler to implement for constant evaluation.
Proposed resolution (approved by CWG 2023-05-12):
Change in 6.7.4 [basic.life] paragraph 1 as follows:
The lifetime of an object o of type T ends when:When evaluating a new-expression, storage is considered reused after it is returned from the allocation function, but before the evaluation of the new-initializer (7.6.2.8 [expr.new]). [ Example:
- if T is a non-class type, the object is destroyed, or
- if T is a class type, the destructor call starts, or
- the storage which the object occupies is released, or is reused by an object that is not nested within o (6.7.2 [intro.object]).
struct S { int m; }; void f() { S x{1}; new(&x) S(x.m); // undefined behavior }
-- end example ]