C++ Logo

std-discussion

Advanced search

Lifetime and destruction of a result object when initialization does not complete due to an exception

From: Артём Колпаков <ddvamp007_at_[hidden]>
Date: Wed, 1 Apr 2026 10:32:01 +0300
As I read the standard:

   - According to [intro.execution]/5
   <https://eel.is/c++draft/intro.execution#5>, an *init-declarator* in a
   *declaration-statement* is a *full-expression*. The same paragraph states
   <https://eel.is/c++draft/intro.execution#5.sentence-4> that
   initialization is part of the full-expression. Therefore, completion of the
   initialization of a variable (and thus the completion of its creation)
   requires completion of the corresponding full-expression.
   - According to [stmt.dcl]/2 <https://eel.is/c++draft/stmt.dcl#2>, a
   variable becomes *active* only after its init-declarator is complete
   (i.e., after control proceeds to the next full-expression or statement).
   Only then is it subject to destruction when control exits its lifetime.
   - According to [dcl.init.general]/16.6.1
   <https://eel.is/c++draft/dcl.init.general#16.6.1>, when an object is
   initialized from a prvalue of the same type, the initializer expression is
   used to initialize the *destination object*.
   - According to [basic.lval]/5 <https://eel.is/c++draft/basic.lval#5>, a
   prvalue generally has a *result object*. Combined with the previous
   point, this implies that a prvalue can directly initialize the destination
   object (i.e., the variable being initialized), without introducing
   intermediate temporaries. This is also consistent with
   [class.temporary]/2 <https://eel.is/c++draft/class.temporary#2>.
   - According to [class.temporary]/4
   <https://eel.is/c++draft/class.temporary#4>, temporary objects are
   destroyed as the last step in evaluating the full-expression that
   (lexically) contains their creation, even if that evaluation exits via an
   exception.

Consider the following example:

struct B {
  ~B() noexcept (false) { throw 0; }
};

struct S {};

int main() {
  S s = (B{}, S{});
}

In this case, the full-expression includes (in evaluation order):

   1. construction of B
   2. construction of S
   3. initialization of s (directly from the prvalue S)
   4. destruction of B

However, the destruction of B throws an exception. Therefore, the
full-expression does not complete normally, and control does not proceed to
the next full-expression or statement.

>From the above premises, it appears that:

   - the initialization of s does not complete,
   - s does not become active,
   - and thus s is not subject to destruction.

At the same time, the result object of the prvalue S appears to have been
constructed directly in the storage of s (as the destination object), i.e.,
no separate temporary object exists.

This seems to leave the standard without a clear rule describing how such a
constructed result object is to be destroyed, since:

   - it is not a temporary (and thus not covered by [class.temporary]/4),
   - and it is not an active variable (and thus not subject to destruction
   via [stmt.dcl]/2).

For comparison, in the case of an expression-statement:

int main() {
  (B{}, S{});
}

both objects are temporaries, and their destruction is fully specified by
[class.temporary].

A similar question arises for reference initialization:

int main() {
  S &&s = (B{}, S{});
}

By analogous reasoning:

   - the lifetime of the reference s does not begin (since initialization
   does not complete),
   - therefore, there is no lifetime extension of a temporary bound to the
   reference.

What, then, is the status of the S object in this case?

One possible model is that a temporary becomes “bound to the reference”
only once the lifetime of the reference begins, implying a transition from
“temporary” to “temporary with extended lifetime”. However, the standard
does not appear to describe such a transition explicitly.

I would appreciate clarification on whether the above reasoning is
incorrect, or whether this scenario is indeed underspecified.

Received on 2026-04-01 07:32:24