函数返回的 RVO 和 rvalue 如何工作
How does RVO and rvalue returned by the function work?
为了理解编译器如何选择类的构造函数,我编写了以下代码:
#include <iostream>
struct Widget
{
Widget(Widget&& w){std::cout << "Move ctor" << std::endl;}
Widget(void){std::cout << "Default ctor" << std::endl;}
Widget(const Widget& w){std::cout << "Copy ctor" << std::endl;}
};
Widget make_widget(void) //helper function
{
Widget w;
return w;
}
int main(void)
{
Widget w(make_widget());
}
根据有效现代C++的第 25 项,由于返回值优化,编译器将 w 视为右值引用。所以我期望Widget w(make_widget())
调用移动构造函数。但事实并非如此。进一步移动,它只打印
Default
所以我不知道调用了哪个版本的构造函数。然后我也尝试显式返回 rvalue。也就是说,return std::move(w)
.考虑到上述结果,我的期望与我相反,它正确地调用了移动构造函数,并打印了
Default
Move
看来我处于价值的迷宫中。请告诉我那里发生了什么。
根据有效现代C++的第 25 项,由于返回值优化,编译器将
w
视为右值引用。
不,我敢肯定作者不是那个意思。 RVO 与是否为右值引用无关。make_widget
和 main
中的w
是 Widget
类型的左值。 如果你有一个类型 Widget&&
的变量,它的值类别是左值(因为它有一个恒等式),它的类型是右值引用。
您看到的Default
是由于make_widget()
内部Widget w;
。 由于返回值优化,避免了将其复制到main
中的w
的操作,因此您看不到更多内容。如果您想在没有 RVO 的情况下查看输出,请在使用它时将-fno-elide-constructors
传递给g++
(无法使用 VC++ 禁用 RVO),您将看到
Default (first creation)
Move (creation of temporary with the move ctor)
Move (copying of temporary to the one in main)
当您将return w
更改为 return std::move(w)
时,为返回创建的临时是用右值构造的,因此您会在输出中看到一个额外的 Move。
相关文章:
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?