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!

2
  • stackoverflow.com/questions/4203010/… Commented Mar 23, 2017 at 12:04
  • 1
    Thank you @dmi. This gave me some insight, however it did not seem to answer my question properly. Commented Mar 23, 2017 at 12:27

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you @Angew! Does this make sure that I am not using unnecessary any intermediate object?
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().
@JCKaz Yes, it guarantees that. I've changed the wording to make it more obvious.
@Angew You my friend, deserve a cookie! Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.