考虑这个例子:
#include <utility> // runtime dominated by argument passing template <class T> void foo(T t) {} int main() { int i(0); foo<int>(i); // fast -- int is scalar type foo<int&>(i); // slow -- lvalue reference overhead foo<int&&>(std::move(i)); // ??? }
foo< int&&>(i)和foo< int>(i)一样快,还是像foo< int&>(i)那样涉及指针开销?
编辑:正如所建议的,运行g -S给了我相同的51行汇编文件foo< int>(i)和foo< int&>(i),但foo< int&&>(std :: move(i))产生了71行汇编代码(看起来差异来自std :: move).
编辑:感谢那些推荐具有不同优化级别的g -S的人 – 使用-O3(以及制作foo noinline),我能够获得看起来像xaxxon’s solution的输出.
解决方法
在您的具体情况下,它们可能都是一样的.来自godbolt与gcc -O3的结果代码是
https://godbolt.org/g/XQJ3Z4:
#include <utility> // runtime dominated by argument passing template <class T> int foo(T t) { return t;} int main() { int i{0}; volatile int j; j = foo<int>(i); // fast -- int is scalar type j = foo<int&>(i); // slow -- lvalue reference overhead j = foo<int&&>(std::move(i)); // ??? }
是:
mov dword ptr [rsp - 4],0 // foo<int>(i); mov dword ptr [rsp - 4],0 // foo<int&>(i); mov dword ptr [rsp - 4],0 // foo<int&&>(std::move(i)); xor eax,eax ret
volatile int使得编译器无法优化掉所有代码,因为它会知道调用的结果被丢弃,整个程序将优化为空.
但是,如果你强制函数不被内联,那么事情会改变一点int __attribute __((noinline))foo(T t){return t;}:
int foo<int>(int): # @int foo<int>(int) mov eax,edi ret int foo<int&>(int&): # @int foo<int&>(int&) mov eax,dword ptr [rdi] ret int foo<int&&>(int&&): # @int foo<int&&>(int&&) mov eax,dword ptr [rdi] ret
上图:https://godbolt.org/g/pbZ1BT
对于这样的问题,学会爱https://godbolt.org和https://quick-bench.com/(快速工作台要求你学习如何正确使用谷歌测试)