复制省略是一种巧妙的优化技术,在某些情况下,依赖复制省略实际上比“手动”传递引用要快。
因此,让我们假设您已经确定了一个关键代码路径,您依靠编译器执行复制省略这一事实来获取代码路径以获得最佳性能。
但是现在您依赖于编译器优化。
是否有任何(编译器特定的,显然)方法来确保实际执行复制省略并在无法执行复制省略时让编译器(或其他工具)生成警告/错误?
(我正在考虑一些与 Visual C++ 很相似的东西,__forceinline
如果这样标记的函数没有被编译器内联,则会生成警告。)
不是真的,除了assert(false);
在复制构造函数中放一个。
否则,请使用您最喜欢的分析器来衡量您的应用程序的有趣部分是否足够快。
不。
但是您可以编写一个等效的,尽管完全不可读的代码:
BigObj f()
{
BigObj x(g());
x.someMethod();
return x;
}
//...
BigObj z = f();
//...
被翻译(带有复制省略)为:
void f(BigObj* obj)
{
new(obj) BigObj(g());
obj->someMethod();
}
//...
char z[sizeof(BigObj)];
f((BigObj*)&z[0]);
//...
((BigObj*)&z[0])->~BigObj();
但说真的,只需以编译器可以忽略副本的方式编写代码。即只返回一个对象而不分支:
BigObj f()
{
BigObj x, y;
// use x and y
if(condition)
return x;
else
return y;
// cannot be elided
}
BigObj f()
{
if(condition)
{
BigObj x;
return x;
}
else
{
BigObj y;
return y;
}
// can be elided
}
在 C++1z(预计 2017 年)中,需要某些情况来保证复制省略:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
根据公共 cppreference.com 编译器功能支持 wiki GCC 7+ 和 Clang 4+ 确保这一点。
幸运的是,优化方面不需要启用更新的语言支持,因为它是纯粹的优化(遵循旧的语言标准允许)。
当优化应用时允许复制构造函数不可用可能需要在编译期间启用较新的语言标准,或者使用不需要严格一致性的松散或扩展模式(例如可能的 GCC's -fpermissive
)。