I have lost faith (and probably 2 hours) in my understanding of what happens when exception is thrown (from constructor) during initialization of member object.
Let me show you the example:
int init (int f) {
throw f;
}
struct X {
X (int f) : n {init (f)} {}
int n;
};
struct P {
X x {20};
};
and the usage:
int main (int argc, char** argv) {
try {
P p {};
}
catch (int n) {
std::cout << n << "\n";
}
}
This code (C++11 mode) compiles fine (using GCC 7.2.1) and under the Linux (Centos 7.4.1708) I get:
terminate called after throwing an instance of 'int'
[1] 1242 abort (core dumped) ./main
Question is: Why?
Why catch()
section was not taken?
I have tracked the issue, meaning that when my P
class looks a little bit different:
struct P {
P (int f) : x {f} {}
X x;
};
and with initialization of p
object in this form: P p {20}
result is: 20, which was expected, no core dump.
Could someone explain me what is the difference between initializing a member using brace-or-equal-initializer and member-initializer-list in the context of exceptions?
Bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85363
The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.
Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
Constructor is a special non-static member function of a class that is used to initialize objects of its class type. In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual bases and non-static data members.
Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.
There should be no practical difference between:
struct P {
X x {20};
};
and
struct P {
P() : x{20} { }
X x;
};
But there's a GCC bug for C++11 mode (but not C++14 or later) which causes the initialization of p{}
to happen outside the try-block, or adds the equivalent of noexcept
to the implicitly-defined default constructor for
P
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With