I am new at C++ and this is my first post here. I am trying to understand initializer lists. The problem is that I get more and more confused. I have made a simple program, that is of no use, but I get a warning I don't understand.
#include <iostream>
using namespace std;
class Base{
private:
string monkey2 = "";
string monkey1 = "";
public:
Base(string) : monkey2{monkey1}{
cout << "monkey1 " << monkey1 << endl;
cout << "monkey2 " << monkey2 << endl;
}
};
int main()
{
return 0;
}
The warning I get is:
field 'monkey' is uninitialized when used here
and an arrow pointing on the row directly below public:
.
The strange thing is if I change the order of the strings from:
private:
string monkey2 = "";
string monkey1 = "";
public:
To:
private:
string monkey1 = "";
string monkey2 = "";
public:
The warning disappears and I don't understand why. I can compile it using g++ but when using my editor vim with YCM and Clang 7.0.0 i get a warning. I have tried to activate as much warnings as i can in g++, but I can not get the same warning. Is my code or. or is it Clang?
Data member are initialized in the order they are declared. Hence, when you have
class Base {
public:
Base();
private:
string monkey2 = "";
string monkey1 = "";
};
the variable monkey2
will be initialized before monkey1
, irrespective of what the ctor Base::Base()
does. This can lead to hard to spot issues, when the initialization of data members depend on each other. Here,
Base() : monkey2{monkey1} { /* ... */ }
monkey2
is initialized by monkey1
, but due to the order of declaration, monkey1
isn't initialized at this point as monkey2
gets initialized first. That's why you get the warning, and that's also why the warning is mitigated by declaring monkey1
first - then, monkey1
is set to ""
via the in-class initializer and monkey2
is initialized with the already initialized monkey1
.
The following (admittedly subjective) guidelines apply to such a scenario:
Base::Base(string)
implementation (see C.48).