C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relax condition for potentially invoked destructor in constructor

From: organicoman <organicoman_at_[hidden]>
Date: Sat, 26 Feb 2022 12:27:33 +0400
To Arvind,This is what i've send you."An object at construction does not call its destructor, in case of exception or error.A destructor exists only if the instantiated object had successfully been constructed."And the following is its detailed explanation. An object is only considered to have started its lifetime when the(non-delegating) constructor for that object returns. In aconstructor, base classes are initialized first (declaration order),then members (also declaration order), and finally the body of theconstructor. Only when an object is constructed successfully can it bedestroyed.If a member's initialization fails via an exception, then the objectthat it was a member of was *never constructed*. Its destructor doesnot get called because its constructor never concluded, let alonebegan. This means that the outer object never really existed.A destructor only gets called on objects that were successfullyconstructed. In the case of a member's initialization throwing anexception, any members & base classes that were successfullyconstructed up to that point are destroyed, in reverse declarationorder.So let's thank Jason for his time to write all this.Now to Jason,Your ultimate point, that each constructor currently already needs tokeep track of which objects have been constructed, is wrong. Becauseeach constructor initializes subobjects in the same order, anyparticular constructor only has to keep track of how many subobjectshave been initialized before the exception. When the exceptionhappens, it can simply jump to the destruction code for destroying allprior objects. Because they all share the same construction ordering,they all share the same destruction ordering too.That was not my ultimate point,I used the idea of "keep track", to explain to others that in certain way we already know from where to start destroying our object under construction. What you want would require each constructor to have its own set ofdestruction orderings to match their separate construction ordering.No! I'm not saying that.Plus, you turn a very simple rule (subobjects are initialized indeclaration order) into a complex one (subobjects are initializedmaybe in declaration order and maybe not, depending on theconstructor).Yes it is a simple idea, and its implementation is lazy.First of all, let me explain what i mean by keep track.1- we should understand that member initialization list i.e subobject members construction, is just a list of calls to constructors.2- constructors are simply functions, most of them are inlined, few of them are actual function calls.3- calling these functions (i.e member constructors) in the context of constructing the object, is creating a stack frame.4- raising an exception during this process, is just a matter of unwinding that stack frame. call it back tracking.So physically we are using the "Stack Segment" to keep track of what was successfully constructed in the list of subobject members, right! LIFOThere is no custom destructors involved, no extra mechanism to handle destructions, nothing. It is already implemented by default.If you want C++ to be an intuitive language, one key tothat is to have simple rules.Yes very much, i want.The current implementation which assumes that the member initialization list calls the member subobjects constructors in order of declaration, otherwise garbage is produced.This is disaster!Where is the difficulty to implement it the following way:1- At compile time, scan the constructor member initialization list.2- create a dependency graph.3- make sure that class subobjects are initialized first in their order of inheritance. 4- generate code for the constructor under compilation, which will call the member subobjects constructors in different order than their declaration order in the class, as per the user wish.Isn't more intuitive?As a program writer, i will be free to not watch in which order i initialize my member objects, when writing my constructor. It is so flexible and saves the day.An object constructor is sensible piece of code, making it non-intuitive could lead to disaster. Just imagine this scenario:" some developer want to write the constructor of a defibrillator, then by mistake he didn't respect the order of initialization of just one member object, now his defibrillator instead of starting at ZERO volts power, it starts at a random value. Two consequences, either his code damages the machine, or kills the patient"That's why, I'm taking the pain the keep answering. Otherwise, I don't care!NadirSent from my Galaxy
-------- Original message --------From: Jason McKesson via Std-Proposals <std-proposals_at_[hidden]> Date: 2/26/22 9:39 AM (GMT+04:00) To: std-proposals_at_[hidden] Cc: Jason McKesson <jmckesson_at_[hidden]> Subject: Re: [std-proposals] Relax condition for potentially invoked
  destructor in constructor On Fri, Feb 25, 2022 at 7:28 PM organicoman via Std-Proposals<std-proposals_at_[hidden]> wrote:>> Here's an abbreviated version illustrating the behavior: https://godbolt.org/z/63G5v63h3>> The output is:> ctor> dtor> Exception: boom>> The ctor/dtor are for "f1", and there is no ctor/dtor for the other "f2".> Which means the destructor does know from where to start destroying, right?No.An object is only considered to have started its lifetime when the(non-delegating) constructor for that object returns. In aconstructor, base classes are initialized first (declaration order),then members (also declaration order), and finally the body of theconstructor. Only when an object is constructed successfully can it bedestroyed.If a member's initialization fails via an exception, then the objectthat it was a member of was *never constructed*. Its destructor doesnot get called because its constructor never concluded, let alonebegan. This means that the outer object never really existed.A destructor only gets called on objects that were successfullyconstructed. In the case of a member's initialization throwing anexception, any members & base classes that were successfullyconstructed up to that point are destroyed, in reverse declarationorder.Your ultimate point, that each constructor currently already needs tokeep track of which objects have been constructed, is wrong. Becauseeach constructor initializes subobjects in the same order, anyparticular constructor only has to keep track of how many subobjectshave been initialized before the exception. When the exceptionhappens, it can simply jump to the destruction code for destroying allprior objects. Because they all share the same construction ordering,they all share the same destruction ordering too.What you want would require each constructor to have its own set ofdestruction orderings to match their separate construction ordering.Plus, you turn a very simple rule (subobjects are initialized indeclaration order) into a complex one (subobjects are initializedmaybe in declaration order and maybe not, depending on theconstructor). If you want C++ to be an intuitive language, one key tothat is to have simple rules.-- Std-Proposals mailing listStd-Proposals_at_[hidden]://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-02-26 08:27:41