☰
string s = “hello“; string t = std::move(s); t是什么类型?
2026/11/4 3:09:35 网站建设 项目流程

std::move 之后,t到底是什么类型?

先看这段代码:

std::string s="hello";std::string t=std::move(s);

运行后,t是std::string&&吗?

结论

t的类型就是std::string,不是std::string&&。

关键是要把「表达式的类型」和「变量的类型」分开来看。

逐步拆解

1.std::move(s)只是一个类型转换

std::move(s)等价于static_cast<std::string&&>(s),作用是把具名变量s从 lvalue 转成 xvalue。

这个表达式的类型确实是std::string&&,但它在运行时什么都不做,不会移动任何东西。

2. 真正的移动发生在初始化t时

编译器会匹配到std::string的移动构造函数(形参类型为std::string&&),并用它来构造t。当字符串较长时,t会直接接管s持有的堆内存指针。

3.t的类型由声明决定

t的声明类型由等号左边决定,即std::string。

此外,C++ 中所有具名变量都是 lvalue,哪怕它是通过移动构造出来的。所以t本身是 lvalue,以后想再把t的内容移走,还得写std::move(t)。

用decltype验证

#include<string>#include<type_traits>intmain(){std::string s="hello";std::string t=std::move(s);static_assert(std::is_same_v<decltype(t),std::string>);// t 是 std::stringstatic_assert(std::is_same_v<decltype(std::move(s)),std::string&&>);// 表达式 move(s) 才是 &&static_assert(std::is_same_v<decltype((t)),std::string&>);// 给 t 加括号得到 lvalue 引用}

用g++ -std=c++17或clang++ -std=c++17编译,三条断言都能通过。

小结

对象类型值类别
std::move(s)std::string&&xvalue
tstd::stringlvalue
(t)std::string&(decltype结果)lvalue

补充:移动后的s是什么状态?

移动之后,标准只保证s处于「有效但未指定」的状态,不保证它为空。

libstdc++ 和 libc++ 通常会把它清空,但这属于实现行为,依赖它一定为空是不可移植的做法。移动后的s只应该被赋新值、销毁,或调用没有前置条件的操作(如clear())。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询