CWG Issue 2721 (original) (raw)
This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 117a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-04-13
2721. When exactly is storage reused?
Section: 6.7.4 [basic.life]Status: DRWPSubmitter: Richard SmithDate: 2023-03-23
[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:
- 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]). 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:
struct S { int m; };
void f() { S x{1}; new(&x) S(x.m); // undefined behavior }
-- end example ]