C++ Logo


Advanced search

Re: Accessing data members in constructors' function try bocks

From: Matthew House <mattlloydhouse_at_[hidden]>
Date: Thu, 19 Jan 2023 08:29:33 -0500
On Thu, Jan 19, 2023 at 4:29 AM Frank B. Brokken via Std-Discussion
<std-discussion_at_[hidden]> wrote:
> It's obvious that class type data members cannot be used in
> constructor function-try-block handlers, as their destructors have
> already been called by the time execution enters those handlers, but
> as basic-type data members don't have destructors they remain
> available for as long as the object's memory remains available (or
> am I missing something and are there some spooky things going on by
> the time the handlers begin their executions?).

All objects have lifetimes and are bound by [basic.life], so even
scalar subobjects will be destroyed before the handler is entered.

This is made explicit by 14.3 [except.ctor] para. 3:

  If the initialization of an object other than by delegating
  constructor is terminated by an exception, the destructor is invoked
  for each of the object's subobjects that were known to be
  initialized by the object's initialization and whose initialization
  has completed (9.4). [...] The subobjects are destroyed in the
  reverse order of the completion of their construction. Such
  destruction is sequenced before entering a handler of the
  function-try-block of the constructor or destructor, if any.

as well as 6.7.3 [basic.life] para. 1:

  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 [...]

alongside 6.7.3 [basic.life] para. 7:

  [...] after the lifetime of an object has ended and before the
  storage which the object occupied is reused or released, [...] The
  program has undefined behavior if:
  - the glvalue is used to access the object, or [...]

However, the wording for this clause, as well as 11.4.7 [class.cdtor]
para. 13 which specifies the order of destruction of subobjects after
an ordinary destructor returns, is somewhat sloppy. In particular,
subobjects of non-class type do not have any destructor to invoke, but
instead a pseudo-destructor which destroys them when called (
[expr.call] para. 5). But I still believe it is the intent that all
subobjects are destroyed one way or another; otherwise, it would have
been explicitly written that "the destructor is invoked for each of
the object's *non-class* subobjects", or something to that effect.

Received on 2023-01-19 13:29:45