【发布时间】:2012-07-29 15:57:13
【问题描述】:
struct A {
A(int) : i(new int(783)) {
std::cout << "a ctor" << std::endl;
}
A(const A& other) : i(new int(*(other.i))) {
std::cout << "a copy ctor" << std::endl;
}
~A() {
std::cout << "a dtor" << std::endl;
delete i;
}
void get() {
std::cout << *i << std::endl;
}
private:
int* i;
};
const A& foo() {
return A(32);
}
const A& foo_2() {
return 6;
}
int main()
{
A a = foo();
a.get();
}
我知道,返回对本地值的引用是不好的。但是,另一方面,const 引用应该延长一个临时对象的生命周期。
此代码产生一个 UB 输出。所以没有延长寿命。
为什么?我的意思是有人可以逐步解释发生了什么吗?
我的推理链哪里出错了?
foo():
A(32) - 演员
return A(32) - 创建并返回对本地对象的 const 引用
A a = foo(); - a被foo()返回值初始化,返回值超出范围(out of expression)被销毁,但是a已经被初始化了;
(但实际上析构函数是在复制构造函数之前调用的)
foo_2():
return 6 - 隐式创建类型 A 的临时对象,创建对该对象的 const 引用(延长其寿命)并返回
A a = foo(); - a被foo()返回值初始化,返回值超出范围(out of expression)被销毁,但是a已经被初始化了;
(但实际上析构函数是在复制构造函数之前调用的)
【问题讨论】:
-
"const 引用应该延长一个临时对象的生命周期" 不扩展它.
-
我认为这就是亚历山大在延长寿命方面所说的:herbsutter.com/2008/01/01/…
-
@Giel:不。常量引用可以延长临时对象的生命周期。在使用临时对象时,常量引用和非常量引用完全不同。在这种情况下,它的工作方式与 OP 似乎期望的不同。
-
@AndreyT:对,vmpstr 给出的链接很好地解释了它。然而,在 OP 的情况下,reference 是返回的临时对象,而不是引用的对象。因此,正如预期的那样,它不会将临时的生命周期延长到产生它的范围之外。我相信后者在所有情况下仍然是正确的:局部对象(临时或作为局部变量)不超出范围。
-
不,他们的生活并没有超出他们的范围,但他们的尸体通常仍然在那里并且“似乎”正在运作和运作,这可能会令人困惑,因为返回参考“似乎工作正常“在某些情况下,但在其他情况下则不然。虽然这是一些额外的工作,但为了防止这种混淆(以及使用过时指针的混淆),我喜欢在删除它们后将析构函数中的成员指针清空,并且在某些情况下将成员变量设置为安全的无效状态,所以如果有人尝试使用已删除的对象,这立即显而易见。
标签: c++ const-reference