c – 左值引用是否与左值引用具有相同的开销?

考虑这个例子:
#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.orghttps://quick-bench.com/(快速工作台要求你学习如何正确使用谷歌测试)

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...