Ale*_*der 7 c++ const-reference
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();
}
Run Code Online (Sandbox Code Playgroud)
我知道,返回对本地值的引用是不好的.但是,另一方面,const引用应该延长临时对象的生命周期.
此代码生成UB输出.所以没有生命延伸.
为什么?我的意思是有人可以解释一下子发生什么事吗?
我的推理链在哪里出错?
FOO():
A(32) - ctor
return A(32) - 创建一个对本地对象的const引用并返回
A = foo(); - a由foo()返回值初始化,返回值超出范围(表达式外)并被销毁,但a已经初始化;
(但实际上析构函数在复制构造函数之前被调用)
FOO_2():
返回6 - 隐式创建类型A的临时对象,创建对该对象的const引用(延长其生命周期)并返回
A = foo(); - a由foo()返回值初始化,返回值超出范围(表达式外)并被销毁,但a已经初始化;
(但实际上析构函数在复制构造函数之前被调用)
AnT*_*AnT 12
在语言规范中明确规定了每个特定上下文的临时生命周期扩展规则.而且它说
12.2临时物体
5第二个上下文是指引用绑定到临时引用.[...]函数返回语句(6.6.3)中返回值的临时绑定将持续存在,直到函数退出.[...]
您的临时对象在函数退出时被销毁.这发生在收件人对象的初始化开始之前.
你似乎认为你的临时生活应该比这更长寿.显然,您正在尝试应用规则,该规则表明临时应该存在直到完整表达式结束.但该规则不适用于在函数内部创建的临时数.这种临时工的生命周期由他们自己的专门规则决定.
如果有人试图使用返回的引用,则您foo和您的foo_2产品都会产生未定义的行为.
您误解了“直到函数退出”。如果您确实想使用 const 引用来延长对象的寿命foo,请使用
A foo() {
return A(32);
}
int main() {
const A& a = foo();
}
Run Code Online (Sandbox Code Playgroud)
如果您希望按照您期望的方式扩展内容,则必须从foo value返回,然后使用 const 引用来引用返回值。
正如 @AndreyT 所说,该对象在具有const &. 您希望您的对象能够在 . 之外继续存在
,因此foo您不应该在. 第一次提到应该是 in ,因为这是应该使对象保持活动状态的函数。const &&foofooconst &main
您可能认为此按值返回代码很慢,因为返回中似乎存在 A 的副本,但这是不正确的。在大多数情况下,编译器只能在其最终位置(即在调用函数的堆栈上)构造 A 一次,然后设置相关引用。
| 归档时间: |
|
| 查看次数: |
3654 次 |
| 最近记录: |