我制作了一个程序来评估这样做的性能差异:
func3(func2(func1()));
与此相比:
retval1 = func1();
retval2 = func2(retval1);
func3(retval2);
我更喜欢后者,因为它更易读和调试。我想知道编译器(MSVC 12.0)是否会在发布版本中优化掉中间对象。我的测试程序如下:
#include <iostream>
using namespace std;
struct Indicator {
Indicator() {cout << "Default constructor" << endl;}
Indicator(const Indicator& other) {cout << "Copy constructor" << endl;}
const Indicator& operator=(const Indicator& other) {cout << "Assignment operator" << endl;}
~Indicator() {cout << "Destructor" << endl;}
};
Indicator func1()
{return Indicator();}
Indicator func2(Indicator&& i)
{return std::move(i);}
Indicator func3(Indicator&& i)
{return std::move(i);}
int main() {
Indicator i = func3(func2(func1()));
cout << &i << endl;
return 0;
}
我很惊讶地发现即使使用了 -O2,仍然会创建三个 Indicator
实例:
Default constructor
Copy constructor
Copy constructor
Destructor
Destructor
00000000002EFC70
Destructor
Press <RETURN> to close this window...
这与我的移动语义理解相冲突,移动语义是指在这种情况下应该只创建一个
Indicator
实例。我还以为编译器应该能够对链接的函数调用使用NRVO。有人可以向我解释一下这里发生了什么吗?