编译器发出std :: move()运行时调用?

时间:2018-04-02 23:09:20

标签: c++

假设以下代码:

// main.cpp
#include <iostream>
#include <string>
#include <utility>

using std::cout;
using std::string;

void print(string && s)
{
    cout << s << '\n';
}

int main()
{
    string sso{"With SSO"};
    string no_sso{"This string is much too large to have SSO, much too large"};

    print(std::move(sso));
    print(std::move(no_sso));
}

使用g++ -g -Wall -Wpedantic -std=c++14 -o move_poc main.cpp编译(结果在msys2和Ubuntu上使用g ++ / clang ++类似)。

查看objdump -d -l -S move_poc的输出,我们得到了这个:

   print(std::move(sso));
c5f:    48 8d 45 a0             lea    -0x60(%rbp),%rax
c63:    48 89 c7                mov    %rax,%rdi
c66:    e8 05 01 00 00          callq  d70
_ZSt4moveIRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEONSt16remove_referenceIT_E4typeEOS8_

c6b:    48 89 c7                mov    %rax,%rdi
c6e:    e8 47 ff ff ff          callq  bba 
_Z5printONSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

c++filt告诉我们第一个受损的符号是(为简洁而编辑)

std::remove_reference<...>::type&& std::move<...>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)

我的理解是std :: move()在运行时没有生成任何东西,我将其解释为&#34; std :: move()是一个编译时操作&#34;。看看上面生成的程序集,似乎我弄错了。

std :: move()应该在运行时做什么吗?或者,由于使用-O2进行编译会消除此调用,这只是在没有优化的情况下进行编译的结果吗?

1 个答案:

答案 0 :(得分:3)

  

我的理解是std :: move()在运行时没有生成任何东西,我将其解释为&#34; std :: move()是一个编译时操作&#34;。看看上面生成的程序集,似乎我弄错了。

不,你做得对,但它仍然是一个函数调用,并且关闭了优化,你的编译器故意不会删除其他&#34;毫无意义的&#34;调用。这是为了帮助调试。

这也是为什么&#34;优化关闭&#34;这种编译模式的描述很差;它更像是&#34;使目标代码与原始源代码相似,而不是实际需要的#34;。 &#34;优化开启的真正含义&#34;是&#34;做一个正确的工作,将这个抽象的程序描述转化为真实的,可以以有用和有效的方式执行#34;。当然,在15世纪,C程序是对您希望执行计算机执行的操作的逐步描述,并在此上下文中进行了优化&#34;优化&#34;在这个过程中有一些意义......但是很长一段时间都没有这种情况。

  

std :: move()应该在运行时做什么吗?

不,它的影响纯粹是&#34;编译时&#34;从某种意义上说,它评估你给它的表达式,但有一个不同的值类别(纯粹的&#34;编译时&#34;概念)。它实际上并没有&#34;做&#34;任何东西。

  

或者,由于使用-O2进行编译可以摆脱这个调用,这只是在没有优化的情况下进行编译的结果吗?