C++ 返回本地对象右值引用,对还是错?
我看到,一旦返回一个本地对象,编译器将对返回值进行优化(RVO,NRVO) RVO的标准祝福部分接着说,如果 满足RVO的条件,但编译器选择不执行 复制省略,返回的对象必须视为右值 因此,我们只需编写如下代码:C++ 返回本地对象右值引用,对还是错?,c++,c++11,C++,C++11,我看到,一旦返回一个本地对象,编译器将对返回值进行优化(RVO,NRVO) RVO的标准祝福部分接着说,如果 满足RVO的条件,但编译器选择不执行 复制省略,返回的对象必须视为右值 因此,我们只需编写如下代码: Widget makeWidget() { Widget w; … return w;//never use std::move(w); } Widget&& makeWidget() { Widget w; … return std::move(w);
Widget makeWidget()
{
Widget w;
…
return w;//never use std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
我从未见过有人编写这样的代码:
Widget makeWidget()
{
Widget w;
…
return w;//never use std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
我知道返回局部对象的左值引用总是错误的。
因此,返回本地对象的右值引用也是错误的?不幸的是
Widget w代码>位于堆栈上,当您将引用向下传递到另一个函数时,w
将被销毁。。。通过值传递对象将避免对象被破坏。返回对局部自动变量的引用总是错误的。当函数返回时,变量将被销毁,因此引用的任何使用都将给出未定义的行为
它是右值引用还是左值引用没有区别。是的,它是错误的。没有发生引用生存期扩展,因此引用引用了一个已销毁的值,使用它(几乎)1是未定义的行为。不应返回悬空引用或指针
1:decltype
不是真正的用途,但它也不是UB。就是这样。存储对它的引用也不重要。也不是真正使用。当函数返回时,本地对象已被释放
如果编写如下代码:
Widget makeWidget()
{
Widget w;
…
return w;//never use std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
Widget&& makeWidget()
{
Widget w;
…
return std::move(w);
}
请考虑以下三个部分代码:
第一名:
Widget&& w= makeWidget();//w is a dangling reference,variable will be destroyed when the function returns
void foo(Widget&& w){...}//w is a dangling reference too
foo(makeWidget());
void foo(Widget w){...}//OK,will copy it
foo(makeWidget());
秒:
Widget&& w= makeWidget();//w is a dangling reference,variable will be destroyed when the function returns
void foo(Widget&& w){...}//w is a dangling reference too
foo(makeWidget());
void foo(Widget w){...}//OK,will copy it
foo(makeWidget());
第三名:
Widget&& w= makeWidget();//w is a dangling reference,variable will be destroyed when the function returns
void foo(Widget&& w){...}//w is a dangling reference too
foo(makeWidget());
void foo(Widget w){...}//OK,will copy it
foo(makeWidget());
所以答案是错的。
请注意:
右值引用可用于延长可修改临时变量的生存期(注意,对const的左值引用也可延长生存期,但它们不可修改)
每当引用绑定到的临时子对象或基子对象时
一个临时的,临时的生存期被延长以匹配
引用的生存期,包括以下异常情况:
- 在return语句中与函数返回值的临时绑定不会被扩展:它会在结束时立即被销毁
返回表达式。此类函数始终返回悬空引用。
- 函数调用中引用参数的临时绑定一直存在,直到包含该参数的完整表达式结束
函数调用:如果函数返回的引用超过
完整的表达,它成为一个悬而未决的参考
- 临时绑定到新表达式中使用的初始值设定项中的引用,直到包含
新的表达式,没有初始化对象那么长。如果初始化的对象超过完整表达式,则其引用成员
成为一个悬而未决的参考
这段引语很混乱。你从哪里弄来的?对象永远不是右值;表达式是右值。“我知道返回右值的左值引用总是错误的”这也是错误的。Widget&makeWidget(){Widget w;…return w;}这是错误的是的。但是你对什么是右值和什么不是右值感到困惑。@LightnessRacesinOrbit-谢谢,我知道了,我把右值改成了本地对象。那会是什么“堆”呢?哦,是的,会的。现在的大多数编译器优化内存,不复制返回值,只需将返回值传递给函数调用方即可。你把右值和临时对象混为一谈了。第一次使用“rvalue”应该是“临时对象”。“右值引用指向右值”不清楚;右值引用可能绑定到右值,右值可能是临时对象,也可能不是临时对象,逗号后面的内容没有意义。引用可能绑定到临时对象,然后该对象被销毁(使引用悬空)。@MattMcNabb请告诉我右值和临时对象的区别,谢谢。rvalue有名称还是有长寿命?没有。临时对象是一种对象。右值是一种表达式。表达式没有名称或生命周期。(对象有生命周期,可能有名字,也可能没有名字)。@MattMcNabb我需要重新组织语言,改变我的答案,thanks@MattMcNabb临时对象是否为右值?谢谢