This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-04-18


2227. Destructor access and default member initializers

Section: 11.9.3  [class.base.init]     Status: CD5     Submitter: Richard Smith     Date: 2016-02-01

[Accepted as a DR at the March, 2018 (Jacksonville) meeting.]

There is implementation divergence on the validity of the following:

   class X { ~X(); };
   struct Y { X x = {}; };

Should X's destructor be potentially invoked by this attempt to initialize an X object? Or,

   auto *y = new Y {};

No constructor for Y is used, because this is aggregate initialization, and a destructor for X is not strictly necessary as there is no later initialization that might throw, but in the corresponding default constructor case we do require that the destructor be valid.

Perhaps the most consistent answer is that the default member initializer should not potentially invoke the destructor unless it's used (for symmetry with default arguments), but that aggregate initialization should potentially invoke the destructors of all subobjects (including the final one - exceptions could theoretically be thrown between the completion of the construction of the final aggregate element and the notional completion of the construction of the aggregate itself.

Proposed resolution (November, 2017)

  1. Add the following as a new paragraph following 9.4.2 [dcl.init.aggr] paragraph 7:

  2. An aggregate that is a class can also be initialized with a single expression not enclosed in braces, as described in 9.4 [dcl.init].

    The destructor for each element of class type is potentially invoked (11.4.7 [class.dtor]) from the context where the aggregate initialization occurs. [Note: This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown (14.3 [except.ctor]). —end note]

  3. Change 11.4.7 [class.dtor] paragraph 12 as follows:

    ...A destructor is potentially invoked if it is invoked or as specified in 7.6.2.8 [expr.new], 9.4.2 [dcl.init.aggr], 11.9.3 [class.base.init], and 14.2 [except.throw]. A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.