假设以下代码:
// 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进行编译会消除此调用,这只是在没有优化的情况下进行编译的结果吗?
答案 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进行编译可以摆脱这个调用,这只是在没有优化的情况下进行编译的结果吗?
是