【发布时间】:2013-12-18 04:58:11
【问题描述】:
我试图解释为什么一个相当好的 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
这显然不是那么好。所以问题是:
为什么我没有看到在“SLOW”情况下应用了 NRVO 优化?我知道编译器不需要应用 NRVO,但这似乎是一个很常见的简单案例。
一般来说,我尝试鼓励使用“SLOW”风格的代码,因为我发现它更容易调试。
【问题讨论】:
-
优化
-s?如果 Clang 上的-s与 GCC 上的功能相同,我认为这不是您需要的。-O2或-O3是合适的。 -
@jogojapan:虽然
-s没有优化,但实际上并不重要,因为复制省略不是一种优化:它会改变行为而不允许优化改变行为。 “NRVO”是用词不当。 Sane 编译器独立于优化设置应用复制省略。可悲的是,有一种流行的编译器会改变行为。 -
@DietmarKühl 我明白了;我没有意识到这一点。谢谢!
-
@DietmarKühl:从我的角度来看,这无疑是一种优化,因为它提高了性能,问题是是否需要在所有优化级别(包括名义上/其他方面未优化的任何内容)执行此优化build) 或 none,因此行为不会改变。问题在于可移植性最终需要强制或禁止优化跨编译器。我个人认为这是 C++ 的一个角落,程序员必须承担一些责任并对此感到满意。
-
根据 Straustrup 的定义,它确实是一种优化 - 优化器 - 编译器的一部分,消除代码中的冗余操作并调整代码以执行在给定的计算机上更好。
标签: c++ optimization c++11 nrvo