<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 2256</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="2256"></A><H4>2256.
  
Lifetime of trivially-destructible objects
</H4>
<B>Section: </B>6.8.4&#160; [<A href="https://wg21.link/basic.life">basic.life</A>]
 &#160;&#160;&#160;

 <B>Status: </B>CD5
 &#160;&#160;&#160;

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-03-30<BR>


<P>[Accepted as a DR at the February, 2019 meeting.]</P>



<P>According to 6.5 [<A href="https://wg21.link/basic.lookup#1.4">basic.lookup</A>] bullet 1.4, the following example
has defined behavior because the lifetime of <TT>n</TT> extends until its
storage is released, which is after <TT>a</TT>'s destructor runs:</P>

<PRE>
  void f() {
    struct A { int *p; ~A() { *p = 0; } } a;
    int n;
    a.p = &amp;n;
  }
</PRE>

<P>It would be more consistent if the end of the lifetime of all objects,
regardless of whether they have a non-trivial destructor, were treated
the same.</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>CWG agreed with the suggested direction.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<OL>
<LI><P>Change 6.8.4 [<A href="https://wg21.link/basic.life#1">basic.life</A>] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>The <I>lifetime</I> of an object or reference is a runtime
property of the object or reference. <DEL>An object is said
to have <I>non-vacuous initialization</I> if it is of a
class or array type and it or one of its subobjects is
initialized by a constructor other than a trivial default
constructor. [<I>Note:</I> : Initialization by a trivial
copy/move constructor is non-vacuous
initialization. &#8212;<I>end note</I>]</DEL>
<INS>A variable is said to have <I>vacuous
initialization</I> if it is default-initialized and, if it
is of class type or (possibly multi-dimensional) array
thereof, that class type has a trivial default
constructor.</INS> The lifetime of an object of
type <TT>T</TT> begins when:</P>

<UL>
<LI><P>storage with the proper alignment and size for
type <TT>T</TT> is obtained, and</P></LI>

<LI><P>
<DEL>if the object has non-vacuous
initialization,</DEL> its initialization <INS>(if any)</INS>
is
complete <INS>(including vacuous initialization)
(9.5 [<A href="https://wg21.link/dcl.init">dcl.init</A>]</INS>,</P></LI>

</UL>

<P>except that if the object is a union member or subobject
thereof, its lifetime only begins if that union member is
the initialized member in the union
(9.5.2 [<A href="https://wg21.link/dcl.init.aggr">dcl.init.aggr</A>], 11.9.3 [<A href="https://wg21.link/class.base.init">class.base.init</A>]),
or as described in 11.5 [<A href="https://wg21.link/class.union">class.union</A>]. The lifetime
of an object <I>o</I> of type <TT>T</TT> ends when:</P>

<UL>
<LI><P><INS>if <TT>T</TT> is a non-class type, the object
is destroyed, or</INS></P></LI>

<LI><P>if <TT>T</TT> is a class type <DEL>with a non-trivial
destructor (11.4.7 [<A href="https://wg21.link/class.dtor">class.dtor</A>])</DEL>, the destructor
call starts, or</P></LI>

<LI><P>the storage which the object occupies is released, or is
reused by an object that is not nested within <I>o</I>
(6.8.2 [<A href="https://wg21.link/intro.object">intro.object</A>]).</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 6.10.3.4 [<A href="https://wg21.link/basic.start.term">basic.start.term</A>] paragraphs 1 and 2 as
follows:</P></LI>

<BLOCKQUOTE>

<P>
<DEL>Destructors (11.4.7 [<A href="https://wg21.link/class.dtor">class.dtor</A>]) for initialized</DEL>
<INS>Constructed</INS>
objects (<DEL>that is, objects whose lifetime
(6.8.4 [<A href="https://wg21.link/basic.life">basic.life</A>]) has begun</DEL>
<INS>9.5 [<A href="https://wg21.link/dcl.init">dcl.init</A>]</INS>) with static storage
duration<DEL>,</DEL> <INS>are destroyed</INS> and functions
registered with <TT>std::atexit</TT><DEL>,</DEL> are called
as part of a call to <TT>std::exit</TT>
(17.5 [<A href="https://wg21.link/support.start.term">support.start.term</A>]).  The call to <TT>std::exit</TT>
is sequenced before the <DEL>invocations of the destructors</DEL>
<INS>destructions</INS> and the registered functions.
[<I>Note:</I> Returning from <TT>main</TT>
invokes <TT>std::exit</TT>
(6.10.3.1 [<A href="https://wg21.link/basic.start.main">basic.start.main</A>]). &#8212;<I>end note</I>]</P>

<P>
<DEL>Destructors for initialized</DEL>
<INS>Constructed</INS> objects with thread storage duration
within a given thread
are <DEL>called</DEL> <INS>destroyed</INS> as a result of
returning from the initial function of that thread and as a
result of that thread
calling <TT>std::exit</TT>. The <DEL>completions of the
destructors for</DEL> <INS>destruction of</INS>
all <DEL>initialized</DEL> <INS>constructed</INS> objects
with thread storage duration within that thread strongly
happen<INS>s</INS> before <DEL>the initiation of the
destructors of</DEL> <INS>destroying</INS> any object with
static storage duration.</P>

</BLOCKQUOTE>

<LI><P>Change 8.8 [<A href="https://wg21.link/stmt.jump#2">stmt.jump</A>] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

...[<I>Note:</I> However, the program can be terminated (by
calling std::exit() or std::abort()
(17.5 [<A href="https://wg21.link/support.start.term">support.start.term</A>]), for example) without destroying
<DEL>class</DEL> objects with automatic storage
duration. &#8212;<I>end note</I>]

</BLOCKQUOTE>

<LI><P>Change 8.10 [<A href="https://wg21.link/stmt.dcl#2">stmt.dcl</A>] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

It is possible to transfer into a block, but not in a way
that bypasses declarations with initialization (including
ones in <I>condition</I>s and <I>init-statement</I>s). A program
that jumps<SUP>92</SUP> from a point where a
variable with automatic storage duration is not in scope to
a point where it is in scope is ill-formed unless the
variable has <DEL>scalar type, class type with a trivial default
constructor and a trivial destructor, a cv-qualified version
of one of these types, or an array of one of the preceding
types and is declared without an <I>initializer</I></DEL>
<INS>vacuous initialization</INS>
(9.5 [<A href="https://wg21.link/dcl.init">dcl.init</A>]). <INS>In such a case, the variables with
vacuous initialization are constructed in the order of their
declaration.</INS> [<I>Example:</I>...

</BLOCKQUOTE>

<LI><P>Change 8.10 [<A href="https://wg21.link/stmt.dcl#5">stmt.dcl</A>] paragraph 5 as follows:</P></LI>

<BLOCKQUOTE>

<DEL>The destructor for a</DEL> <INS>A</INS> block-scope
object with static or thread storage duration will
be <DEL>executed</DEL> <INS>destroyed</INS> if and only if
it was constructed. [<I>Note:</I>
6.10.3.4 [<A href="https://wg21.link/basic.start.term">basic.start.term</A>] describes the
order in which block-scope objects with static and thread
storage duration are destroyed. &#8212;<I>end note</I>]

</BLOCKQUOTE>

<LI><P>Change 9.5 [<A href="https://wg21.link/dcl.init#21">dcl.init</A>] paragraph 21 as follows:</P></LI>

<BLOCKQUOTE>

An object whose initialization has completed is deemed to be
constructed, even if <INS>the object is of non-class type
or</INS> no constructor of the object's class is invoked for
the initialization. [<I>Note:</I> Such an object might have
been value-initialized or initialized by aggregate
initialization (9.5.2 [<A href="https://wg21.link/dcl.init.aggr">dcl.init.aggr</A>]) or by an
inherited constructor
(11.9.4 [<A href="https://wg21.link/class.inhctor.init">class.inhctor.init</A>]). &#8212;<I>end note</I>]
<INS>Destroying an object of class type invokes the destructor
of the class. Destroying a scalar type has no effect other than
ending the lifetime of the object (6.8.4 [<A href="https://wg21.link/basic.life">basic.life</A>]).
Destroying an array destroys each element in reverse subscript
order.</INS>

</BLOCKQUOTE>

<LI><P>Change 11.4.7 [<A href="https://wg21.link/class.dtor#2">class.dtor</A>] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<DEL>A destructor is used to destroy objects of its class
type.</DEL> The address of a destructor...

</BLOCKQUOTE>

<LI><P>Change 14.3 [<A href="https://wg21.link/except.ctor">except.ctor</A>] paragraphs 1 and 2 as
follows:</P></LI>

<BLOCKQUOTE>

<P>As control passes from the point where an exception is
thrown to a handler, <DEL>destructors are invoked</DEL>
<INS>objects with automatic storage duration are
destroyed</INS> by a process, specified in this subclause,
called <I>stack unwinding</I>.</P>

<P>
<DEL>The destructor is invoked for each automatic object of class
type</DEL>
<INS>Each object with automatic storage duration is
destroyed if it has been</INS> constructed, but not yet
destroyed, since the try block was entered. If an exception
is thrown during the destruction of temporaries or local
variables for a return statement
(8.8.4 [<A href="https://wg21.link/stmt.return">stmt.return</A>]), the destructor for the
returned object (if any) is also invoked. The objects are
destroyed in the reverse order of the completion of their
construction. [<I>Example:</I>...</P>

</BLOCKQUOTE>

</OL>

<BR><BR>
</BODY>
</HTML>
