编译器会生成std::move()的运行时调用吗?(附代码示例)
std::move会生成运行时调用吗?
问题背景
假设存在以下代码:
// 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
(在macOS/Linux环境下使用g++/clang++编译结果类似)
提问:编译器会生成std::move()的运行时调用吗?
解答
咱们先戳破一个常见误区:std::move本身不会生成任何运行时调用,它本质上是一个编译期的类型转换工具,完全是编译器在编译阶段处理的“语法糖”。
具体来说:
- std::move的底层实现是一个模板函数,它的作用仅仅是把传入的左值(或者任何表达式)转换成对应的右值引用类型,这个转换过程没有任何运行时的指令开销,只是告诉编译器“把这个对象当作右值来处理”。
- 当你在代码里写
std::move(sso)时,编译器在编译阶段就完成了类型转换,不会生成调用std::move的运行时函数指令——哪怕你用-g保留调试信息,也不会看到std::move的运行时调用记录。
再结合你给出的代码和编译选项补充两点:
- 对于
print函数接收右值引用的操作,真正的运行时动作是字符串的移动(或者说对字符串内部资源的转移):- 对于SSO(小字符串优化)的
sso,因为字符串内容存在栈上,移动操作其实就是简单的内存拷贝(开销极小); - 对于
no_sso这种超出SSO长度的字符串,移动操作只是转移堆内存的指针,同样开销很低,但这些都和std::move本身无关。
- 对于SSO(小字符串优化)的
- 哪怕你不开启优化(比如没加
-O系列选项),std::move依然不会产生运行时调用——它的类型转换逻辑完全在编译阶段完成,不需要运行时介入。
内容的提问来源于stack exchange,提问作者PCaetano
相关产品推荐
相关产品推荐

