Return 堆分配变量的值优化和初始化
Return Value Optimization And Initializaton of Heap Allocated Variables
从临时 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就可以直接在堆分配的chunk中构造了?
编辑:
使用 g++(i686-posix-dwarf-rev0,由 MinGW-W64 项目构建)5.3.0 编译,使用 -O3 -std=c++17
编辑 2:
更新到 MinGW 7.4.0,现在它优化了复制和移动。
它可以,需要额外的努力,the rules of C++17 actually require your compiler to go to this effort。
所以进入 C++17 模式并尽情享受吧!
(live demo)
如果您出于某种原因不想使用 C++17,只要您使用支持它的编译器,那么它很可能会在早期的标准模式中应用此优化(因为他们已经不得不编写执行此操作的代码)。例如,即使在 -O0
,Coliru 的 GCC 在 C++14 模式下也是如此。换句话说,也许你只需要升级你的编译器。
如果您的编译器不在 C++17 模式下执行此操作,则它 non-compliant 符合标准。
这可能是一个错误,例如 this old GCC bug; MinGW-w64 v5.0.3 should approximate to GCC 7.2.0,我知道这个错误需要修复,但由于 MinGW 不是 GCC 代码库的直接克隆,因此它在这方面可能略有落后。您可以尝试升级到 MinGW-x64 v6。
我还发现 Visual Studio 2017 的复制省略不可靠。
从临时 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就可以直接在堆分配的chunk中构造了?
编辑:
使用 g++(i686-posix-dwarf-rev0,由 MinGW-W64 项目构建)5.3.0 编译,使用 -O3 -std=c++17
编辑 2: 更新到 MinGW 7.4.0,现在它优化了复制和移动。
它可以,需要额外的努力,the rules of C++17 actually require your compiler to go to this effort。
所以进入 C++17 模式并尽情享受吧!
(live demo)
如果您出于某种原因不想使用 C++17,只要您使用支持它的编译器,那么它很可能会在早期的标准模式中应用此优化(因为他们已经不得不编写执行此操作的代码)。例如,即使在 -O0
,Coliru 的 GCC 在 C++14 模式下也是如此。换句话说,也许你只需要升级你的编译器。
如果您的编译器不在 C++17 模式下执行此操作,则它 non-compliant 符合标准。
这可能是一个错误,例如 this old GCC bug; MinGW-w64 v5.0.3 should approximate to GCC 7.2.0,我知道这个错误需要修复,但由于 MinGW 不是 GCC 代码库的直接克隆,因此它在这方面可能略有落后。您可以尝试升级到 MinGW-x64 v6。
我还发现 Visual Studio 2017 的复制省略不可靠。