Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 返回本地对象右值引用,对还是错?_C++_C++11 - Fatal编程技术网

C++ 返回本地对象右值引用,对还是错?

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);

我看到,一旦返回一个本地对象,编译器将对返回值进行优化(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 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临时对象是否为右值?谢谢