Reputation: 383
what is wrong with this code, why do I get wrong answer:
class X
{
private:
const int a;
const int& b;
public:
X(): a(10) , b(20)
{
// std::cout << "constructor : a " << a << std::endl;
// std::cout << "constructor : b " << b << std::endl;
}
void display()
{
std::cout << "display():a:" << a << std::endl;
std::cout << "display():b:" << b << std::endl;
}
};
int
main(void)
{
X x;
x.display();
return 0;
}
The above code will give me the result as
display():a:10
display():b:1104441332
But If I remove the commented 2 lines inside the default constructor it gives me proper result which is
constructor : a 10
constructor : b 20
display():a:10
display():b:20
please help, Thank you
Upvotes: 21
Views: 5552
Reputation: 104698
b
refers to a temporary. What you have read (when printing) is an invalid location by the time it is read since the temporary 20
has technically gone out of scope.
To explain inconsistent results:
It is undefined behavior. What you see may be different if you:
x
You should always always avoid undefined behavior.
But why would the value change? Your reference likely refers to a stack address which has been rewritten (e.g. reused) by the time it's printed.
Upvotes: 4
Reputation: 340316
You're binding the const&
to a temporary, which doesn't live beyond the call to the constructor. The C++03 standard specfically says "a temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits" (12.2/5 "Temporary objects").
So your code has undefined behavior - you might get nonsense, or something that appears to be 'working'.
FWIW, MSVC 2010 gives the following warning on that code:
C:\temp\test.cpp(12) : warning C4413: 'X::b' : reference member is initialized to a temporary that doesn't persist after the constructor exits
Upvotes: 3
Reputation: 234584
I'll let my compiler answer this one:
$ g++ -std=c++98 -Wall -Wextra -pedantic test.cpp
test.cpp: In constructor 'X::X()':
test.cpp:9:26: warning: a temporary bound to 'X::b' only persists until the constructor exits [-Wextra]
$
You should turn on the warnings on your compiler as well.
Upvotes: 19
Reputation: 98509
You are initializing b
as a reference to a temporary.
The value 20
is created and exists only for the scope of the constructor.
The behavior of the code after this is very interesting - on my machine, I get different values from the ones you posted, but the fundamental behavior is still nondeterministic.
This is because when the value to which the reference points falls out of scope, it begins to reference garbage memory instead, giving unpredictable behavior.
See Does a const reference prolong the life of a temporary?; the answer https://stackoverflow.com/a/2784304/383402 links to the relevant section of the C++ standard, specifically the below text:
A temporary bound to a reference member in a constructor’s ctor-initializer
(12.6.2) persists until the constructor exits.
This is why you always get the right value in the print within the constructor, and rarely (but possibly sometimes!) after. When the constructor exits, the reference dangles and all bets are off.
Upvotes: 24