6月1日 10:30

C++ 移动语义和完美转发怎么用?std::move/forward 原理详解

C++11 引入移动语义解决不必要的深拷贝问题。核心在于区分左值(可取地址、具名)和右值(临时、不可取地址)。右值引用 T&& 可绑定到右值,表示该对象资源可被"窃取"而非复制。移动构造函数和移动赋值运算符通过转移资源(如指针、文件句柄)而非复制,显著提升性能。std::move 本质是无条件转为右值引用的 static_cast,并不移动任何东西,只是让重载决议选择移动版本。完美转发指函数模板将参数以原始值类别(左值/右值)传递给另一函数,借助 std::forward<T> 实现。T&& 在模板推导中是万能引用:实参为左值时 T 推导为左值引用,实参为右值时 T 推导为非引用类型,配合 std::forward<T> 按原始类别转发。引用折叠规则决定了最终类型:只有 T&& && 折叠为 T&&,其余均折叠为 T&

追问

std::move 之后原对象还能用吗?

可以,但处于"有效但未指定"状态。可安全赋值或析构,不应读取其值。移动后应将原对象置空或重置,保持语义清晰。

万能引用和右值引用怎么区分?

看 T 是否需要推导:template<typename T> void f(T&& x) 中 T&& 是万能引用;void f(std::string&& x) 中是右值引用。auto&& 也是万能引用。

完美转发中为什么必须用 std::forward 而非 std::move?

std::move 总是转为右值,会错误地将左值参数也转为右值。std::forward<T> 仅当 T 为非引用类型时才转为右值,保留原始值类别。

引用折叠的四种情况是什么?

T& & → T&T& && → T&T&& & → T&T&& && → T&&。只有右值引用到右值引用折叠为右值引用,其余均折叠为左值引用。

标签:C++