Date: Thu, 24 Feb 2022 17:22:07 +0400
From what i understand from the standardees above, is that : during the construction of an object of type T, if an exception is thrown due to an exception(i.e error) during the construction of one of its subobjects, then all the subobjects that have been constructed successfully are allowed to call their destructors to free their resources. Why? Because if the object of type T is not completely constructed then it cannot call its destructor, which in turn doesn't call its subjects destructors, which leaks resources if those subobjects are fully constructed.In your proposal, you are giving this wording a different rephrasing plus imposing an order upon the possibility of calling destructors.But remember that the compiler is free to rearrange the construction of subobjects for optimization purposes, thus by following your proposal you prevent the compiler from optimazing the order of construction. That's why the cpp standard says "potentially constructed", i.e either constructed or postponed for later construction. I hope it was clear.Nadir Sent from my Galaxy
-------- Original message --------From: Kilian Henneberger via Std-Proposals <std-proposals_at_[hidden]> Date: 2/24/22 11:08 AM (GMT+04:00) To: std-proposals_at_[hidden] Cc: Kilian Henneberger <kilis-mail_at_[hidden]> Subject: [std-proposals] Relax condition for potentially invoked destructor in constructor
Hello,
https://eel.is/c++draft/class.base.init#12
says:
In a non-delegating constructor, the
destructor for each potentially constructed subobject of class
type is potentially invoked ([class.dtor]);
Below there is also a motivating note https://eel.is/c++draft/class.base.init#note-5:
This provision ensures that destructors can be called for
fully-constructed subobjects in case an exception is thrown
([except.ctor]).
The note makes sense. But I think the paragraph #12 is too
restrict. See following example:
---
class PublicInterface {
std::unique_ptr<class Impl> pimpl_;
};
---
For the (compiler generated) default constructor of PublicInterface, class.base.init#12
requires that the destructor of pimpl_
is potentially invoked,
even if there is no possible code path in the (compiler
generated) default constructor of PublicInterface
which actually might invoke it.
I would like to propose to relax paragraph #12. I am not a
wording-expert, but in my own words I would change it to
something like:
"In a non-delegating constructor of type T, the destructor for
each potentially constructed subobject S of class type is
potentially invoked,
if there is any potentially throwing code after the
construction of S and before the end of the constructor of T."
Here are a few examples for what I am aiming at:
---
class FirstExample {
std::string a_; //destructor is
potentially invoked, because the constructor of b_ (taking a const
char*) isn't noexcept.
std::string b_ = "Hello"; //destructor is not potentially
invoked, because the constructor of c_
(default constructor) is noexcept.
std::string c_; //destructor is not
potentially invoked, because there are no further member.
};
class SecondExample {
std::string d_; //destructor is potentially
invoked, because the initializer of e_
(new int) can throw.
int* e_ = new int;
};
void ThisCanThrow();
class ThirdExample {
std::string f_;
ThirdExample() { ThisCanThrow(); } //destructor of f_ is potentially invoked, because
the body of the constructor of ThirdExample
calls a potentially throwing function.
};
---
I would very much welcome your feedback.
Best Regards
Kilian
-------- Original message --------From: Kilian Henneberger via Std-Proposals <std-proposals_at_[hidden]> Date: 2/24/22 11:08 AM (GMT+04:00) To: std-proposals_at_[hidden] Cc: Kilian Henneberger <kilis-mail_at_[hidden]> Subject: [std-proposals] Relax condition for potentially invoked destructor in constructor
Hello,
https://eel.is/c++draft/class.base.init#12
says:
In a non-delegating constructor, the
destructor for each potentially constructed subobject of class
type is potentially invoked ([class.dtor]);
Below there is also a motivating note https://eel.is/c++draft/class.base.init#note-5:
This provision ensures that destructors can be called for
fully-constructed subobjects in case an exception is thrown
([except.ctor]).
The note makes sense. But I think the paragraph #12 is too
restrict. See following example:
---
class PublicInterface {
std::unique_ptr<class Impl> pimpl_;
};
---
For the (compiler generated) default constructor of PublicInterface, class.base.init#12
requires that the destructor of pimpl_
is potentially invoked,
even if there is no possible code path in the (compiler
generated) default constructor of PublicInterface
which actually might invoke it.
I would like to propose to relax paragraph #12. I am not a
wording-expert, but in my own words I would change it to
something like:
"In a non-delegating constructor of type T, the destructor for
each potentially constructed subobject S of class type is
potentially invoked,
if there is any potentially throwing code after the
construction of S and before the end of the constructor of T."
Here are a few examples for what I am aiming at:
---
class FirstExample {
std::string a_; //destructor is
potentially invoked, because the constructor of b_ (taking a const
char*) isn't noexcept.
std::string b_ = "Hello"; //destructor is not potentially
invoked, because the constructor of c_
(default constructor) is noexcept.
std::string c_; //destructor is not
potentially invoked, because there are no further member.
};
class SecondExample {
std::string d_; //destructor is potentially
invoked, because the initializer of e_
(new int) can throw.
int* e_ = new int;
};
void ThisCanThrow();
class ThirdExample {
std::string f_;
ThirdExample() { ThisCanThrow(); } //destructor of f_ is potentially invoked, because
the body of the constructor of ThirdExample
calls a potentially throwing function.
};
---
I would very much welcome your feedback.
Best Regards
Kilian
Received on 2022-02-24 13:22:15