Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor member initialization lists explained

Tags:

c++

The question is in the topic - I don't think I understand how member initialization list is different from direct initialization in the constructor body.

Suppose the following code:

template<typename T>
class MyClass
{
public:
    explicit MyClass(const T& val) : val_(val) {}
private:
    T val_;
    MyClass(const MyClass &other) = delete;
    MyClass(const MyClass &&other) = delete;
    MyClass& operator=(const MyClass &other) = delete;
    MyClass& operator=(const MyClass &&other) = delete;
};

template<typename R>
class MyOtherClass
{
public:
    explicit MyOtherClass(const R& val)
    : stuff_(val)
    {
        //stuff_(val); <-- does not work
    }   
private:
    MyClass<R> stuff_;
};

int main()
{
    MyOtherClass<int> my_value(34);
}

So why does : stuff_(val) work while ...{ stuff_(val); } gives following error:

error: no matching function for call to ‘MyClass<int>::MyClass()’
  {
  ^
test.cpp:5:11: note: candidate: MyClass<T>::MyClass(const T&) [with T = int]
  explicit MyClass(const T& val) : val_(val) {}
           ^
test.cpp:5:11: note:   candidate expects 1 argument, 0 provided

[P.S.] The code is with templates because from the start I wanted to ask a different question, but was not able to reproduce it on this code snippet. In my production code I have something similar to this:

template<typename R>
class MyOtherClass
{
public:
    explicit MyOtherClass(const R& val)
    {
        stuff_(val); 
        another_stuff_(56);
    }   
private:
    MyClass<R> stuff_;
    MyClass<int> another_stuff_;
};

And it gives me error only on another_stuff_(56). Trying to figure out what is the difference for now.

like image 303
arbulgazar Avatar asked Jun 30 '26 18:06

arbulgazar


1 Answers

stuff_(val); doesn't match any initialization syntax. It's trying call stuff_ as a functor and pass val as argument.

Furthermore, when goes into the body of the contructor, the initialization of stuff_ has been finished. In other words you cannot perform initialization in the body of the constructor (you might perform assignment or something else). If you specify the member initializer list, the appropriate constructor is called to initialize it before entering constructor. If not, it'll be default initialized (In your example it fails because MyClass doesn't have default constructor, as the error message said).

like image 54
songyuanyao Avatar answered Jul 02 '26 09:07

songyuanyao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!