右值引用与左值引用具有相同的开销吗?

时间:2018-08-14 03:01:00

标签: c++ c++11 overhead pass-by-rvalue-reference

考虑以下示例:

#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给了foo<int>(i)foo<int&>(i)相同的51行汇编文件,但是foo<int&&>(std::move(i))产生了71行汇编代码(看来差异来自std::move)。

编辑:感谢那些建议g++ -S使用不同优化级别的人-使用-O3(并制作foo noinline),我能够得到看起来像{{3} }。

2 个答案:

答案 0 :(得分:5)

在您的特定情况下,它们可能都是相同的。带有gcc -O3的Godbolt产生的代码是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 j使得编译器无法优化所有代码,因为否则它会知道调用结果将被丢弃,整个程序将没有优化。

但是,如果您强制不内联函数,则情况会发生一些变化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/(快速工作台要求您学习如何正确使用 google测试

答案 1 :(得分:5)

参数传递的效率取决于ABI。

例如,在Linux上,Itanium C++ ABI指定将引用作为指向所引用对象的指针进行传递:

  

3.1.2参考参数

     

通过将指针传递给实际参数来处理参考参数。

这与引用类别(rvalue / lvalue引用)无关。

从更广泛的角度来看,我在丹麦技术大学calling convention的一份文档中找到了这句话,该文档分析了大多数编译器:

  

在所有方面,引用都被视为与指针相同。

因此右值和左值引用涉及所有ABI的指针开销。