假设以下代码:
// 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() 在运行时不会生成任何内容,我将其解释为“std::move() 是一个编译时操作”。看看上面生成的程序集,看来我弄错了。
std::move() 应该在运行时执行任何操作吗?或者,由于使用 -O2 编译消除了此调用,这是否只是未经优化编译的结果?
最佳答案
It was my understanding that std::move() didn't generate anything at runtime, which I interpreted as "std::move() is a compile-time operation". Looking at the generated assembly above, it seems I got it wrong.
不,你说得对,但它仍然是一个函数调用,并且在关闭优化的情况下,你的编译器故意不会删除其他“无意义”的调用。这是为了帮助调试。
这也是为什么“优化关闭”对于这种编译模式来说是一个糟糕的描述;它更像是“使目标代码比实际需要的更类似于原始源代码”。 “优化打开”的真正含义是“正确地将程序的抽象描述转化为可以以有用且高效的方式执行的真实内容”。当然,在 15 世纪,C 程序是对您希望执行计算机执行的操作的逐步描述,在这种情况下,在流程之上进行“优化”是有一定道理的……但这并没有”很长一段时间都是这样。
Is std::move() supposed to do anything at runtime?
不,它的效果纯粹是“编译时”,因为它计算您给它的表达式,但具有不同的值类别(纯粹的“编译时”概念)。它实际上并没有“做”任何事情。
Or, since compiling with -O2 gets rid of this call, is this just a result of compiling without optimization?
是的。
关于c++ - 编译器发出 std::move() 运行时调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49620000/