复制省略是一种巧妙的优化技术,在某些情况下,依靠复制省略实际上比手动传递引用更快。
因此,假设您已经确定了一个关键代码路径,您依赖于编译器对代码路径执行复制省略以实现最大性能。
但现在您依赖于编译器优化。
是否有任何(特定于编译器的)方法可以确保实际执行复制省略,并让编译器(或其他工具)生成警告/错误,如果无法执行复制省略?
(我想到了与Visual C++的__forceinline
类似的远程功能,如果标记为这样的函数未被编译器内联,则会生成警告。)
复制省略是一种巧妙的优化技术,在某些情况下,依靠复制省略实际上比手动传递引用更快。
因此,假设您已经确定了一个关键代码路径,您依赖于编译器对代码路径执行复制省略以实现最大性能。
但现在您依赖于编译器优化。
是否有任何(特定于编译器的)方法可以确保实际执行复制省略,并让编译器(或其他工具)生成警告/错误,如果无法执行复制省略?
(我想到了与Visual C++的__forceinline
类似的远程功能,如果标记为这样的函数未被编译器内联,则会生成警告。)
不行。
但你可以编写等效的代码,尽管它完全无法阅读:
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
}
swap
只是一个特例。通常情况下,您可以通过在顶部添加 T return_value
,将具有多个返回值的函数转换为单个返回值,将每个返回语句更改为对 return_value
的赋值,并最终返回 return_value
。通常,这种模式可以进一步优化,例如通过使用合理的值初始化 return_value
。 - MSalters除了在复制构造函数中放置assert(false);
外,没有其他方法。
否则,请使用您喜欢的分析器来测量应用程序的有趣部分是否足够快。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
根据cppreference.com编译器特性支持维基,GCC 7+和Clang 4+可以保证这一点。 -fpermissive
)。-Wnrvo
选项。