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!
source to share
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
.