While asking this question, I learned const reference to a temporary object is valid in C++:
int main ()
{
int a = 21;
int b = 21;
//error: invalid initialization of non-const reference
//int & sum = a + b;e [...]
//OK
int const & sum = a + b;
return sum;
}
But in the following example, the const reference refnop
refers to a destroyed temporary object. I wonder why?
#include <string>
#include <map>
struct A
{
// data
std::map <std::string, std::string> m;
// functions
const A& nothing() const { return *this; }
void init() { m["aa"] = "bb"; }
bool operator!= (A const& a) const { return a.m != m; }
};
int main()
{
A a;
a.init();
A const& ref = A(a);
A const& refnop = A(a).nothing();
int ret = 0;
if (a != ref) ret += 2;
if (a != refnop) ret += 4;
return ret;
}
Tested using GCC 4.1.2 and MSVC 2010, it returns 4;
$> g++ -g refnop.cpp
$> ./a.out ; echo $?
4
The difference between ref
and refnop
is the call to nothing()
which does really nothing. It seems after this call, the temporary object is destroyed!
My question:
Why in the case of refnop
, the life time of the temporary object is not the same as its const reference?
The lifetime-extension of a temporary object can be performed only once, when the temporary object gets bound to the first reference. After that, the knowledge that the reference refers to a temporary object is gone, so further lifetime extensions are not possible.
The case that is puzzling you
A const& refnop = A(a).nothing();
is similar to this case:
A const& foo(A const& bar)
{
return bar;
}
//...
A const& broken = foo(A());
In both cases, the temporary gets bound to the function argument (the implicit this
for nothing()
, bar
for foo()
) and gets its lifetime 'extended' to the lifetime of the function argument. I put 'extended' in quotes, because the natural lifetime of the temporary is already longer, so no actual extension takes place.
Because the lifetime extension property is non-transitive, returning a reference (that happens to refer to a temporary object) will not further extend the lifetime of the temporary object, with as result that both refnop
and broken
end up referring to objects that no longer exist.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With