Reference variable with error, must be initialized in constructor base/member initializer
Solution 1
First of all, your A::s_
is a reference to a std::string
; that means that it's referencing something that must exists somewhere.
Due of his reference type, and the fact that the references must be initialized at the moment they're created, you must initialize A::s_
in ALL the A
constructors (as pointed by other users):
class A
{
public:
A(string& s) : s_(s)
{ cout << "A::ctor" << endl; }
A(const A& rhs) : s_(rhs.s_) // <-- here too!!
{ cout << "A::copy" << endl; }
~A()
{ cout << "A::dtor" << endl; }
A& operator=(const A& rhs)
{ cout << "A::copyassign" << endl; }
private:
string& s_;
};
And now, back to the first thing I mentioned; the A::s_
must reference something that exists, so you must be aware of some things, take a look at the following code:
int main()
{
// New A instance:
A a("hello world");
return 0;
}
Constructing this A
instance we're providing a const char[12]
value, with this value a temporary std::string
is created and is given to the A::A(string& s)
constructor. Where A::s_
is referencing after the constructor ends? What happens with the temporary std::string
created? It's lifetime is extended or it just die when the A
constructor ends? Are you sure that a reference is what you need?
std::string s("hello world");
int main()
{
// New A instance:
A a(s);
return 0;
}
With the code above, a new A
instance is created calling the same A::A(string& s)
constructor, but with a provided string lying in the global scope, so it doesn't be destroyed and the A::s_
from the a
instance would reference a valid string all its lifetime, but the real threat is in the copy constructor:
std::string s("hello world");
int main()
{
A a(s); // a.s_ references the global s.
A b(a); // b.s_ references the a.s_ that references the global s.
return 0;
}
The copied object value will reference the std::string
of the given object! Is that what you want?
Solution 2
Your copy constructor never initializes the reference. Make sure it does:
A(const A &rhs) : s_(rhs.s_) {cout << "A::copy" << endl;}
Comments
-
Number42 over 4 years
I got following error when I try to compile the source-code below. Can anybody describe why this error exists and how I can fix it?
Error 1 error C2758: 'A::s_' : must be initialized in constructor base/member initializer
#include <iostream> #include <string> using namespace std; class A { public: A(string& s) : s_(s) { cout << "A::ctor" << endl; } A(const A& rhs) { cout << "A::copy" << endl; } ~A() { cout << "A::dtor" << endl; } A& operator=(const A& rhs) { cout << "A::copyassign" << endl; } private: string& s_; }; int main() { return 0; }
-
Number42 over 11 yearsThanks a lot for the detailed description.
-
chris over 11 yearsI just want to point out that you can't pass
"hello world"
into it in the first place (i.e. compiler error) as temporaries can't be bound to a non-constant reference. -
PaperBirdMaster over 11 years@chris it worked for me. The temporary created at the
A a("hello world")
call is bounded to thea.s_
reference. -
PaperBirdMaster over 11 yearsMy bad! you're right! silly me! :( this proves that make
std::string
references as members and make a non-explicit constructor is even worse than i thought!