Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing exception from member constructor (brace initializer vs initializer list)

Tags:

c++

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

like image 388
Artur Pyszczuk Avatar asked Feb 21 '18 15:02

Artur Pyszczuk


People also ask

What is the advantage of using member initializer list?

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.

When must you use a member initializer list?

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.

Is constructor same as initializer?

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.

When should a constructor use an initializer?

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.


1 Answers

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.

like image 99
Jonathan Wakely Avatar answered Oct 20 '22 15:10

Jonathan Wakely