Correct way to initialize custom struct object in class constructor

In the constructor, myClass in the code below is initialized 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 ms

are the arguments to the ms constructor. What happens here, in essence, is that we use what we call "list initialization" to create an unnamed (anonymous) object myStruct

: "{4,5}", and then we pass that object to the constructor ms

. So, in principle, an anonymous intermediate object is created, copied for initialization ms

, and then destroyed (although I'm sure the compiler knows better and initializes ms

directly; there is still a semantic difference). I was told that instead ms({4,5})

I could just do

ms(4,5)

      

and avoid creating 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 is the best practice in terms of initializing a struct object in a class constructor. All help is greatly appreciated!

+3


source to share


1 answer


I was told that instead ms({4,5})

I could just doms(4,5)

This is almost correct, but not quite. You can actually do this ms{4,5}

, that is, use the direct-list initialization for the member ms

. This way it will use the normal list initialization rules, which in your case will trigger aggregate initialization.



In other words, the element ms

will be initialized directly in place, without creating any temporary type objects myStruct

.

+2









All Articles