c++ - 堆分配变量的返回值优化和初始化
问题描述
从临时 RVO 初始化堆栈分配的变量时会发生,但在初始化堆分配的变量时不会发生。
#include <iostream>
using namespace std;
class A
{
public:
A() = default;
A(const A &other)
{
cout << "Copy A!" << endl;
}
A(A &&other)
{
cout << "Move A!" << endl;
}
};
A foo()
{
return A();
}
int main()
{
A a1 = foo(); //Constructs A only!
A *a2 = new A(foo()); //Constructs A and moves it
}
输出:移动A!
在我看来编译器是在堆栈中创建A,获取堆分配内存的指针然后移动A,但是为什么不只是先获取指针然后将其传递给foo,所以可以直接构造A在堆分配的块?
编辑:使用 g++ (i686-posix-dwarf-rev0,由 MinGW-W64 项目构建) 5.3.0 编译,使用-O3 -std=c++17
编辑 2:更新到 MinGW 7.4.0,现在它优化了复制和移动。
解决方案
它可以,只需付出一点额外的努力,C++17 的规则实际上需要你的编译器去努力。
所以换上 C++17 模式,尽情享受吧!
(现场演示)
如果您出于某种原因不想使用 C++17,只要您使用支持它的编译器,那么它很可能会在早期的标准模式中应用此优化(因为他们已经必须编写代码来做到这一点)。例如,Coliru 的 GCC 即使在-O0
. 换句话说,也许您只需要升级您的编译器。
如果您的编译器在 C++17 模式下不这样做,则它不符合标准。
这可能是一个错误,就像这个旧的 GCC 错误;MinGW-w64 v5.0.3应该近似于 GCC 7.2.0,我理解要修复的错误,但由于 MinGW 不是 GCC 代码库的直接克隆,它在这方面可能会稍微落后。您可以尝试升级到 MinGW-x64 v6。
我还发现 Visual Studio 2017 的复制省略不可靠。
推荐阅读
- flutter - '响应的实例
'颤动Api消费 - angular - Angular 9 cdk 虚拟滚动 - 即使用户滚动,滚动索引也不会改变
- git - 如何在 Git 中获取一组文件的所有作者?
- webhooks - 将已部署智能合约的事件链接到 webhook
- html - 在 Angular 8 中获取表单提交的表单值
- r - 在 R 中跨多列过滤行
- javascript - 如何使用 Jquery 对数组进行排序
- docker - 如何解决在 Windows 7 上运行的 docker 工具箱中的此错误我尝试通过添加共享文件夹来配置虚拟框
- mysql - 使用 MySQL 查询从 Joomla 中的文章中删除链接
- flutter - 可以mapEventToState同一个实例