在函数作用域(生命周期)之后,对临时对象的 const 引用被破坏
在问这个问题时,我学会了const引用到临时对象在 C++ 中是有效的:
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;
}
但是在下面的例子中,const 引用 refnop
引用了一个被破坏的临时对象.我想知道为什么?
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;
}
使用 GCC 4.1.2 和 MSVC 2010 测试,返回 4;
Tested using GCC 4.1.2 and MSVC 2010, it returns 4;
$> g++ -g refnop.cpp
$> ./a.out ; echo $?
4
ref
和 refnop
之间的区别在于对 nothing()
的调用实际上什么都不做.看来这次调用之后,临时对象就被销毁了!
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!
我的问题:
为什么在refnop
的情况下,临时对象的生命周期与其const引用不同?
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.
让你困惑的案例
A const& refnop = A(a).nothing();
类似于这种情况:
A const& foo(A const& bar)
{
return bar;
}
//...
A const& broken = foo(A());
在这两种情况下,临时变量都绑定到函数参数(nothing()
的隐式 this
, 的
) 并将其生命周期扩展"到函数参数的生命周期.我将'extended'放在引号中,因为临时文件的自然生命周期已经更长,因此不会发生实际的扩展.bar
foo()
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.
因为生命周期扩展属性是不可传递的,返回一个引用(恰好指向一个临时对象)不会进一步延长临时对象的生命周期,结果是 refnop
和 broken
最终指向不再存在的对象.
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.
相关文章