ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

std::move

2026/8/14 22:37:37 拓冰建站 浏览量
std::move std::move是 C11 引入的移动语义核心工具1.功能std::move不移动任何东西它是一个类型转换工具将左值有名字的变量无条件转换为右值引用T从而“骗过”编译器去调用移动构造函数或移动赋值运算符。目的转移资源所有权如堆内存、文件句柄避免深拷贝的开销。效果被移动的对象进入“有效但未指定”的状态通常是空不应再访问其内容除非重新赋值。2. 基础用法2.1 移动构造函数转移堆内存class Buffer { int* ptr; public: // 移动构造函数noexcept 是关键优化提示 Buffer(Buffer other) noexcept : ptr(other.ptr) { other.ptr nullptr; // 防止析构时 double free } }; Buffer a; Buffer b std::move(a); // 触发移动a 变为空指针noexcept是 C11 引入的异常规范修饰符核心作用标记函数不抛异常和编译器优化提示。2.2移动赋值运算符转移并清理旧资源Buffer operator(Buffer other) noexcept { if (this ! other) { delete ptr; // 释放自己的旧资源 ptr other.ptr; // 接管别人资源 other.ptr nullptr; } return *this; } b std::move(a); // 触发移动赋值2.3 STL 容器的高效操作最实用std::vectorstd::string v1 {a, b}; std::vectorstd::string v2 std::move(v1); // O(1) 转移指针不拷贝元素 // 向容器插入大对象避免拷贝 std::vectorMyClass vec; MyClass obj; vec.push_back(std::move(obj)); // 直接转移不复制3. 注意事项1std::move后若要用原变量必须重新赋值后才安全。移动后访问是未定义行为通常崩溃。std::string s hello; std::string t std::move(s); std::cout s; // 未定义行为s 可能为空或乱码 s new; // 重新赋值后可安全使用2只有定义了移动构造函数的类型才高效移动如std::vector。简单类型int拷贝和移动无区别。3const对象用std::moveconst std::vectorint v;即使std::move(v)因为无法修改会退化为拷贝const 右值无法绑定到非 const 移动构造。4. 与std::forward的区别工具作用使用场景std::move无条件转为右值明确要转移资源时std::forward有条件转为右值保留原始类型模板完美转发转发参数给下一层函数templatetypename T void wrapper(T arg) { // 保持 arg 的原始左右值属性 other_func(std::forwardT(arg)); }5.TT在 C 中根据上下文有两种完全不同的含义分别是右值引用和万能引用转发引用。判断标准看T是否被推导。5.1. 右值引用Rvalue Reference当T是具体类型时T就是右值引用。作用绑定到即将销毁的临时对象用于实现“移动语义”窃取资源。特征只能接收右值临时量、std::move的结果。void func(std::vectorint vec) { // T 是具体类型 vectorint // 只能接收右值 } std::vectorint v; func(std::move(v)); // 可以 func(v); // 编译报错左值无法绑定到右值引用5.2. 万能引用Forwarding Reference当T是模板参数且T由实参推导时T是万能引用。作用在模板中保持值类别不变左值保持左值右值保持右值常用于std::forward完美转发。特征既能接收左值也能接收右值。templatetypename T void func(T arg) { // T 由实参推导这里是万能引用 // 传左值 - T 推导为 int // 传右值 - T 推导为 int } int x 10; func(x); // 左值可以 func(20); // 右值也可以func(x)x是左值int→T推导为int→arg类型是int左值引用func(T arg) → func(int arg) 引用折叠→ func(int arg)func(20)20是右值int→T推导为int→arg类型是int右值引用func(T arg) → func(int arg)引用折叠规则原始类型折叠后T TT TT TT T5.3. 特殊情况autoauto也是万能引用同样根据初始化表达式推导auto r1 10; // 右值 - int int x 5; auto r2 x; // 左值 - int4. const T注意const T永远是右值引用不是万能引用且极少使用因为移动时通常不需要 const。