我正在思考一个相当不错的C++11编译器(clang)为何不能优化这段代码,并想知道这里是否有人有意见。
#include <iostream>
#define SLOW
struct A {
A() {}
~A() { std::cout << "A d'tor\n"; }
A(const A&) { std::cout << "A copy\n"; }
A(A&&) { std::cout << "A move\n"; }
A &operator =(A) { std::cout << "A copy assignment\n"; return *this; }
};
struct B {
// Using move on a sink.
// Nice talk at Going Native 2013 by Sean Parent.
B(A foo) : a_(std::move(foo)) {}
A a_;
};
A MakeA() {
return A();
}
B MakeB() {
// The key bits are in here
#ifdef SLOW
A a(MakeA());
return B(a);
#else
return B(MakeA());
#endif
}
int main() {
std::cout << "Hello World!\n";
B obj = MakeB();
std::cout << &obj << "\n";
return 0;
}
如果我注释掉
#define SLOW
并使用-s
进行优化,那么我会得到:Hello World!
A move
A d'tor
0x7fff5fbff9f0
A d'tor
预计会出现这种情况。
如果我启用#define SLOW
并使用-s
进行优化,则会得到以下结果:
Hello World!
A copy
A move
A d'tor
A d'tor
0x7fff5fbff9e8
A d'tor
很明显这种情况并不好。所以问题是:
为什么"慢速"案例中没有应用NRVO优化?我知道编译器不一定需要应用NRVO,但这似乎是一个非常普遍而简单的情况。
总的来说,我尝试鼓励采用"慢速"风格的代码,因为我发现这样更容易调试。
-s
吗?如果Clang上的-s
与GCC上的相同,我认为那不是你所需要的。-O2
或-O3
会更合适。 - jogojapan-s
不会进行优化,但实际上并不重要,因为复制省略不是一种优化:它改变了行为,而优化不允许改变行为。 "NRVO"是一个误称。理智的编译器独立于优化设置应用复制省略。可悲的是,有一个流行的编译器会改变行为。 - Dietmar Kühl