Segmentation fault
Segmentation fault

Reputation: 115

How to initialize class members without using the copy constructor

I'm now writing C++ code to do some maths. However, it seems impossible to use normal constructors to initialize class members.

To get instantiated, the constructor of A is first called. By the time, p and q are just something like declaration so p and q don't get instantiated either. So I should be able to call constructor of B to instantiate them. Is that right? I think maybe my understanding of C++ classes is wrong somewhere so I post here to confirm.

class B{
    // default constructor and copy constructor
}

class A{
private:
    B p;
    B q;
public:
    explicit A(int _p, int _q);
}

// implementation
A::A(int _p, int _q){
    // some computing goes here so I can't apply 
    // A::A(int _p, int _q):p{_p}, q{_q}

    // p = B{_p}
    // q = B{_q} 
    // this works

    p{_p}; // Can't compile.
    q{_q}; // What's wrong with this?
}

Upvotes: 4

Views: 1221

Answers (2)

Rubens
Rubens

Reputation: 14768

The problem is that you simply can't use initialization lists to perform assignments by the way you are trying. And, since you can't initialize the variable at first, you are actually looking for an assignment (notice that p and q have already been default initialized). When you write:

p{_p};
q{_q};

It's just not valid syntax, since there is no operation defined over lvalue<initialization_list> after the variable has already been initialized (at anywhere else out of the constructor's initialization list/variable declaration).

Upvotes: 1

T.C.
T.C.

Reputation: 137330

No, the constructor's behavior actually looks like this:

A::A(/* parameters */)
    : /* member constructors called here, explicitly or by default, in order of declaration */
{
     /* your constructor code */
}

In other words, by the time you enter a constructor's body, all class members are already fully constructed, either from the initializer list if it's specified there, or default-constructed if it is not in the initializer list. Thus, your A constructor behaves as if you wrote A::A(int _p, int _q) : p{}, q{} { /* code */ }. q = B{_q}; does not call the copy constructor; it constructs a temporary B object and calls the copy or move assignment operator of q, but since the compiler generates those for you in many cases, it compiles. q{_q};, as a statement, is simply not valid C++.

Upvotes: 4

Related Questions