编译器优化
所以我有一个问题要问你。 :) 你能告诉我以下代码应该产生的输出吗?
#include <iostream>
struct Optimized
{
Optimized() { std::cout << "ctor" << std::endl; }
~Optimized() { std::cout << "dtor" << std::endl; }
Optimized(const Optimized& copy) { std::cout << "copy ctor" << std::endl; }
Optimized(Optimized&& move) { std::cout << "move ctor" << std::endl; }
const Optimized& operator=(const Optimized& rhs) { std::cout << "assignment operator" << std::endl; return *this; }
Optimized& operator=(Optimized&& lhs) { std::cout << "move assignment operator" << std::endl; return *this; }
};
Optimized TestFunction()
{
Optimized a;
Optimized b = a;
return b;
}
int main(int argc, char* argv[])
{
Optimized test = TestFunction();
return 0;
}
我的第一反应是:
- ctor
- copy ctor
- move ctor
- dtor
- dtor
- dtor
,这是真的,但仅当编译器优化关闭时。当优化打开时,输出完全不同。打开优化后,输出为:
- ctor
- copy ctor
- dtor
- dtor
通过编译器优化,测试变量是返回变量。
我的问题是,什么条件会导致无法以这种方式优化?
我一直被教导,返回一个导致额外复制构造函数的结构/类可以通过作为引用传递来更好地进行优化,但编译器正在为我做这件事。那么 return 结构仍然被认为是不好的形式吗?
So I have a question for you. :)
Can you tell me the output the following code should produce?
#include <iostream>
struct Optimized
{
Optimized() { std::cout << "ctor" << std::endl; }
~Optimized() { std::cout << "dtor" << std::endl; }
Optimized(const Optimized& copy) { std::cout << "copy ctor" << std::endl; }
Optimized(Optimized&& move) { std::cout << "move ctor" << std::endl; }
const Optimized& operator=(const Optimized& rhs) { std::cout << "assignment operator" << std::endl; return *this; }
Optimized& operator=(Optimized&& lhs) { std::cout << "move assignment operator" << std::endl; return *this; }
};
Optimized TestFunction()
{
Optimized a;
Optimized b = a;
return b;
}
int main(int argc, char* argv[])
{
Optimized test = TestFunction();
return 0;
}
My first response would be:
- ctor
- copy ctor
- move ctor
- dtor
- dtor
- dtor
and it IS true, but only if compiler optimization is turned off. When optimization is turned ON then the output is entirely different. With optimization turned on, the output is:
- ctor
- copy ctor
- dtor
- dtor
With compiler optimization, the test variable is the return variable.
My question is, what conditions would cause this to not be optimized this way?
I have always been taught that returning a struct/class which results in extra copy constructors could better be optimized by being passed in as a reference but the compiler is doing that for me. So is return a structure still considered bad form?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这称为“复制省略”,是一种特殊处理,而不是复制/移动。
标准特别允许优化,只要可以复制/移动(即,该方法已声明且可访问)。
在这种情况下,编译器中的实现通常称为“返回值优化”。有两种变体:
return "aa" + someString;
)两者都是由主要编译器实现的,但后者可能仅在更高的优化级别上启动,因为它更难以检测。
因此,要回答您有关返回结构的问题:我会推荐它。考虑一下:
后者不仅更清晰,而且还允许 const 强制执行!
This is known as Copy Elision and is a special handling instead of copying/moving.
The optimization is specifically allowed by the Standard, as long as it would be possible to copy/move (ie, the method is declared and accessible).
The implementation in a compiler is generally referred to, in this case, as Return Value Optimization. There are two variations:
return "aa" + someString;
)Both are implemented by major compilers, but the latter may kick in only at higher optimization levels as it is more difficult to detect.
Therefore, to answer your question about returning structs: I would recommend it. Consider:
The latter is not only clearer, it also allows
const
enforcement!两种输出都是允许的。 C++03 语言标准在第 12.8/15 条中规定:
Both outputs are permissible. The C++03 language standard says, in clause 12.8/15:
此代码将产生的输出是不可预测的,因为语言规范明确允许选择性消除(省略)类对象的“不必要的”临时副本,即使它们的复制构造函数有副作用。
这种情况是否会发生可能取决于多种因素,包括编译器优化设置。
在我看来,将上述复制省略称为“优化”并不完全正确(尽管在这里使用这个术语的愿望是完全可以理解的,并且它被广泛用于此目的)。我想说,术语优化应该保留在编译器偏离抽象C++机器同时保留可观察的行为的情况程序的行为。换句话说,真正的优化意味着违反语言规范的抽象要求。由于在这种情况下没有违规(标准明确允许复制省略),因此没有真正的“优化”。我们在这里观察到的只是 C++ 语言在其抽象级别上的工作方式。根本不需要涉及“优化”的概念。
The output this code will produce is unpredictable, since the language specification explicitly allows optional elimination (elision) of "unnecessary" temporary copies of class objects even if their copy constructors have side effects.
Whether this will happen or not might depend on may factors, including the compiler optimization settings.
In my opinion calling the above copy elision an "optimization" is not entirely correct (although the desire to use this term here is perfectly understandable and it is widely used for this purpose). I'd say that the term optimization should be reserved to situations when the compiler deviates from the behavior of the abstract C++ machine while preserving the observable behavior of the program. In other words, true optimization implies violation of the abstract requirements of the language specification. Since in this case there's no violation (the copy elision is explicitly allowed by the standard), there's no real "optimization". What we observe here is just how the C++ language works at its abstract level. No need to involve the concept of "optimization" at all.
即使按值传回,编译器也可以使用返回值优化来优化额外的副本,请参阅; http://en.wikipedia.org/wiki/Return_value_optimization
Even when passing back by value the compiler can optimise the extra copy away using Return Value Optimisation see; http://en.wikipedia.org/wiki/Return_value_optimization