代码之家  ›  专栏  ›  技术社区  ›  Taylor Nichols

rvalue引用的开销是否与lvalue引用相同?

  •  6
  • Taylor Nichols  · 技术社区  · 6 年前

    举个例子:

    #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&&>(std::move(i)) 产生了71行汇编代码(看起来差异来自 std::move

    编辑:感谢那些推荐 g++-S公司 具有不同的优化级别--使用 -O3 (和制作foo noinline xaxxon's solution .

    2 回复  |  直到 6 年前
        1
  •  5
  •   xaxxon    6 年前

    在你的具体情况下,它们很可能都是一样的。由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 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.org https://quick-bench.com/ (快速板凳要求你学会如何 使用 谷歌测试 )

        2
  •  5
  •   Oliv    6 年前

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

    Itanium C++ ABI 指定将引用作为指向引用对象的指针传递:

    3.1.2参考参数

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

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

    因此,rvalue和lvalue引用涉及所有ABI上的指针开销。

    推荐文章