代码之家  ›  专栏  ›  技术社区  ›  Patrick

为什么要按值传递string_视图?为什么VisualStudio不能对此进行优化?

  •  4
  • Patrick  · 技术社区  · 7 年前

    根据我的直觉,我认为新的string_视图需要通过引用传递,因为这样更有效(只传递指针,而不是完整的类)。然而,一些资料表明,最好按值传递,以避免“别名”问题。

    在尝试几种替代方法时,我证实了我的直觉,即如果函数只转发string_视图(所有源代码都是用 /Ox )

    例如,这个代码

    extern auto otherMethodByReference(const std::string_view &input) -> void;
    auto thisMethodByReference(int value, const std::string_view &input) -> void
       {
       otherMethodByReference(input);
       }
    

    导致了这次集会

    00000   48 8b ca     mov     rcx, rdx
    00003   e9 00 00 00 00   jmp     ?otherMethodByReference@@YAXAEBV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z ; otherMethodByReference
    

    而这个代码

    extern auto otherMethodByValue(std::string_view input) -> void;
    auto thisMethodByValue(int value, std::string_view input) -> void
       {
       otherMethodByValue(input);
       }
    

    导致了这次集会

    00000   48 83 ec 38  sub     rsp, 56            ; 00000038H
    00004   0f 10 02     movups  xmm0, XMMWORD PTR [rdx]
    00007   48 8d 4c 24 20   lea     rcx, QWORD PTR $T1[rsp]
    0000c   0f 29 44 24 20   movaps  XMMWORD PTR $T1[rsp], xmm0
    00011   e8 00 00 00 00   call    ?otherMethodByValue@@YAXV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z ; otherMethodByValue
    00016   48 83 c4 38  add     rsp, 56            ; 00000038H
    0001a   c3       ret     0
    

    很明显,您可以看到string_视图的副本是在堆栈上创建的,然后传递给另一个方法。

    然而,我想知道,为什么编译器不对此进行优化,直接将string_view参数传递给另一个方法呢。毕竟,在Windows x64 ABI中,一个大于寄存器大小的类的传递值总是通过复制堆栈上的寄存器,并在正确的寄存器中传递指向它的指针来完成的。我希望在这个示例代码中,编译器会简单地将指针转发到下一个函数,就像通过引用传递一样。毕竟,编译器可以看到参数的值在之后不会被使用,所以它可以直接转发地址,而不是复制。

    我尝试在通话中添加std::move,如下所示:

    auto thisMethodByValueAndMove(int value, std::string_view input) -> void
       {
       otherMethodByValue(std::move(input));
       }
    

    但这似乎没有帮助。

    Visual Studio 2017编译器无法对此进行优化有什么原因吗? 其他编译器是否优化了这种模式?

    1 回复  |  直到 7 年前
        1
  •  0
  •   NN_    6 年前

    X64调用约定不允许在不同寄存器之间传播参数。 编译器可以通过rcx和rdx传递string_视图,但ABI对此表示反对。 https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019