jkazan
jkazan

Reputation: 1199

Correct way to initialize custom struct object in a class constructor

In the constructor for myClass, in the code below, I initialize ms with ms({4,5}).

#include <iostream>

class myClass {
 private:
  struct myStruct {
    int val1;
    int val2;
  };

public:
  myStruct ms;
  myClass() : ms({4,5}){} // This is where I initialize ms!
};

int main(){
  myClass mc;
  std::cout << mc.ms.val1 << " " << mc.ms.val2 << std::endl;
  return 0;
};

However, we are in the member initialization list, so the arguments to ms are the arguments to the ms's constructor. What happens here, essentially, is that we use the so-called "list initialization" to create an unnamed (anonymous) myStruct object: "{4,5}", and then we pass that object to the constructor of ms. So in principle, the anonymous intermediate object is created, copied to initialize ms, and then destroyed (although I'm pretty sure that the compiler knows better and initializes ms directly; but there is still the semantic difference). I was told that, instead of ms({4,5}) I could simply do

ms(4,5)

and avoid making an intermediate object. However, when I do this, I get the following output:

g++ -g -std=c++11 -Wall temp.cpp -o temp
temp.cpp: In constructor ‘myClass::myClass()’:
temp.cpp:12:21: error: no matching function for call to ‘myClass::myStruct::myStruct(int, int)’
   myClass() : ms(4,5){}
                     ^
temp.cpp:5:10: note: candidate: myClass::myStruct::myStruct()
   struct myStruct {
          ^
temp.cpp:5:10: note:   candidate expects 0 arguments, 2 provided
temp.cpp:5:10: note: candidate: constexpr myClass::myStruct::myStruct(const myClass::myStruct&)
temp.cpp:5:10: note:   candidate expects 1 argument, 2 provided
temp.cpp:5:10: note: candidate: constexpr myClass::myStruct::myStruct(myClass::myStruct&&)
temp.cpp:5:10: note:   candidate expects 1 argument, 2 provided
makefile:15: recipe for target 'temp' failed
make: *** [temp] Error 1

So, to be clear, I am wondering what the best practice is, in terms of initialising a struct object in a class constructor. All help is much appreciated!

Upvotes: 3

Views: 794

Answers (1)

I was told that, instead of ms({4,5}) I could simply do ms(4,5)

That's almost right, but not quite. What you can actually do is ms{4,5}, that is, use direct-list-initialisation for the member ms. That way, it will use normal list initialisation rules, which in your case will invoke aggregate initialisation.

In other words, the member ms will be initialised directly in-place, without creating any temporary objects of type myStruct.

Upvotes: 2

Related Questions