string s = “hello“; string t = std::move(s); t是什么类型? std::move 之后,t到底是什么类型?先看这段代码:std::string shello;std::string tstd::move(s);运行后,t是std::string吗?结论t的类型就是std::string,不是std::string。关键是要把「表达式的类型」和「变量的类型」分开来看。逐步拆解1.std::move(s)只是一个类型转换std::move(s)等价于static_caststd::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验证#includestring#includetype_traitsintmain(){std::string shello;std::string tstd::move(s);static_assert(std::is_same_vdecltype(t),std::string);// t 是 std::stringstatic_assert(std::is_same_vdecltype(std::move(s)),std::string);// 表达式 move(s) 才是 static_assert(std::is_same_vdecltype((t)),std::string);// 给 t 加括号得到 lvalue 引用}用g -stdc17或clang -stdc17编译,三条断言都能通过。小结对象类型值类别std::move(s)std::stringxvaluetstd::stringlvalue(t)std::string(decltype结果)lvalue补充:移动后的s是什么状态?移动之后,标准只保证s处于「有效但未指定」的状态,不保证它为空。libstdc 和 libc 通常会把它清空,但这属于实现行为,依赖它一定为空是不可移植的做法。移动后的s只应该被赋新值、销毁,或调用没有前置条件的操作(如clear())。