3

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!

jkazan
  • 1,149
  • 12
  • 29
  • http://stackoverflow.com/questions/4203010/how-to-initialize-member-struct-in-initializer-list-of-c-class – dmi Mar 23 '17 at 12:04
  • 1
    Thank you @dmi. This gave me some insight, however it did not seem to answer my question properly. – jkazan Mar 23 '17 at 12:27

1 Answers1

2

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.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thank you @Angew! Does this make sure that I am not using unnecessary any intermediate object? – jkazan Mar 23 '17 at 12:26
  • I personally don't recommend this way of initialization as in my opinion it is very risk prone, even in spite it is supported by C++11 standard. As per my personal taste is better to provide a constructor to the struct and initialize it as `ms()`. – dmi Mar 23 '17 at 12:32
  • @JCKaz Yes, it guarantees that. I've changed the wording to make it more obvious. – Angew is no longer proud of SO Mar 23 '17 at 12:52
  • @Angew You my friend, deserve a cookie! Thank you so much! – jkazan Mar 23 '17 at 15:06