ead*_*ead 6 c++ optimization rvo
请看一下这个愚蠢的功能,该功能只能说明问题并简化实际代码:
struct A;
A create(bool first){
A f(21), s(42);
if(first)
return f;
else
return s;
}
Run Code Online (Sandbox Code Playgroud)
我知道,由于不清楚在编译过程中将返回哪个对象,因此我们不能期望总是执行返回值优化(RVO)。
但是,可能会期望在50%的情况下执行RVO(由于缺少更多信息,假设true/的分布均匀false):只需确定应在哪种情况下执行RVO(first==true或first==false)并将其应用于此参数值,接受在另一种情况下必须调用复制构造函数。
但是,并非所有的编译器都可以使用这种“部分RVO”功能(请参见gcc,clang和MSVC的实时介绍)-在两种情况下(即first==true或first==false)都使用了复制构造函数,并且未将其省略。
是否有某种东西会使上述情况下的“部分RVO”无效,或者这是所有编译器都错过优化的不太可能的情况?
完整程序:
#include <iostream>
struct A{
int val;
A(int val_):val(val_){}
A(const A&o):val(o.val){
std::cout<<"copying: "<<val<<"\n";
}
};
A create(bool first){
A f(21), s(42);
if(first)
return f;
else
return s;
}
int main(){
std::cout<<"With true: ";
create(true);
std::cout<<"With false: ";
create(false);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*ely 10
让我们考虑一下如果对RVO完成了会发生什么f,这意味着它直接在返回值中构造。如果first==true和f被退回,很好,不需要副本。但是如果first==false随后s返回它,那么程序将在析构函数运行之前s在其顶部复制构造。然后,析构函数for 将运行,现在返回值是一个已经被销毁的无效对象!f ff
如果s改为进行RVO操作,则应用相同的参数,但现在问题发生在时first==true。
无论您选择哪种方式,都可以在50%的情况下避免复制,而在另50%的情况下获得不确定的行为!这不是理想的优化!
为了完成这项工作,必须更改局部变量的销毁顺序,以便在复制到该内存位置之前f销毁销毁(反之亦然),这是一件非常危险的事情。销毁顺序是C ++的一项基本属性,不应该被搞砸,否则您将破坏RAII,谁知道还有多少其他假设。s
| 归档时间: |
|
| 查看次数: |
230 次 |
| 最近记录: |