std::move 和 std::forward

关联点

都是执行转换(cast)的函数(函数模板),不产生任何可执行代码。且都可以把实参转换成右值。

std::move无条件将实参(const除外 )转换成右值引用,std::forward 条件返回右值引用

python 复制代码
_EXPORT_STD template <class _Ty>
_NODISCARD _MSVC_INTRINSIC constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept {
    return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}
python 复制代码
_EXPORT_STD template <class _Ty>
_NODISCARD _MSVC_INTRINSIC constexpr _Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept {
    return static_cast<_Ty&&>(_Arg);
}

_EXPORT_STD template <class _Ty>
_NODISCARD _MSVC_INTRINSIC constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept {
    static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
    return static_cast<_Ty&&>(_Arg);
}
python 复制代码
_EXPORT_STD template <class _Ty>
struct remove_reference {
    using type                 = _Ty;
    using _Const_thru_ref_type = const _Ty;
};

template <class _Ty>
struct remove_reference<_Ty&> {
    using type                 = _Ty;
    using _Const_thru_ref_type = const _Ty&;
};

template <class _Ty>
struct remove_reference<_Ty&&> {
    using type                 = _Ty;
    using _Const_thru_ref_type = const _Ty&&;
};

_EXPORT_STD template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;

先去引用,然后转换成右值

区别

1. 用途不同

  • std::move
    无条件将左值转换为右值引用,表示对象资源可被"移动"。用于触发移动构造函数或移动赋值运算符,避免深拷贝。
    示例:
cpp 复制代码
std::string s1 = "Hello";
std::string s2 = std::move(s1); // s1 的资源被移动到 s2,s1 不再有效
  • std::forward
    有条件地保持值类别(左值/右值),用于完美转发。通常与万能引用(T&&)配合,在泛型代码中保持参数的原始类型。
    示例:
cpp 复制代码
template<typename T>
void wrapper(T&& arg) {
    callee(std::forward<T>(arg)); // 保持 arg 的原始值类别
}

2. 转换条件

  • std::move
    无论输入是左值还是右值,始终返回右值引用。
cpp 复制代码
auto rval = std::move(lval); // 无条件转为右值
  • std::forward
    根据模板参数 T 的类型决定转换行为:
cpp 复制代码
forward<T>(arg); // 类型 T 决定结果
复制代码
- 若 `T` 是左值引用(如 `int&`),返回左值引用。  
- 若 `T` 是非引用或右值引用(如 `int` 或 `int&&`),返回右值引用。

3. 实现机制

  • std::move** 实现**
cpp 复制代码
template<typename T>
constexpr typename std::remove_reference<T>::type&& move(T&& t) noexcept {
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}

直接通过 static_cast 将输入转换为右值引用。

  • std::forward** 实现**
cpp 复制代码
template<typename T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept {
    return static_cast<T&&>(t);
}

根据 T 的类型推断结果,决定返回左值或右值引用。


4. 应用场景

  • 使用 std::move 的场景
    • 需要明确转移对象资源所有权时(如实现移动构造函数)。
    • 避免拷贝开销,例如将局部变量移动到容器中:
cpp 复制代码
std::vector<std::string> vec;
std::string s = "data";
vec.push_back(std::move(s)); // 移动而非拷贝
  • 使用 std::forward 的场景
    • 泛型函数模板中转发参数,保持其原始值类别:
cpp 复制代码
template<typename... Args>
void emplace(Args&&... args) {
    container.emplace_back(std::forward<Args>(args)...); // 完美转发参数包
}

总结

特性 std::move std::forward
目的 强制转为右值,触发移动语义 保持参数原始值类别,完美转发
转换条件 无条件 依赖模板参数 T
典型应用 移动构造函数、避免拷贝 泛型代码中的参数转发
参数类型 接受任意类型 通常与万能引用 T&& 配合使用

补充:

//拷贝构造

MyStruct(const Mystruct &)

{

}

//移动构造

Mystruct( Mystruct &&) // 无const

{

}

万能引用:

T&&

相关推荐
CoderCodingNo6 分钟前
【GESP】C++一级真题 luogu-B4495, [GESP202603 一级] 交朋友
开发语言·c++
梦游钓鱼21 分钟前
stl常用容器说明
开发语言·c++
WBluuue29 分钟前
Codeforces 1088 Div1+2(ABC1C2DEF)
c++·算法
像素猎人39 分钟前
map<数据类型,数据类型> mp和unordered_map<数据类型,数据类型> ump的讲解,蓝桥杯OJ4567最大数目
c++·算法·蓝桥杯·stl·map
沐雪轻挽萤1 小时前
1. C++17新特性-序章
java·c++·算法
郝学胜-神的一滴1 小时前
从链表到二叉树:树形结构的入门与核心性质解析
数据结构·c++·python·算法·链表
玖釉-1 小时前
深入解析 meshoptimizer:基于 meshopt_computeSphereBounds 的层级包围球构建与 DAG 优化
c++·算法·图形渲染
CoderMeijun1 小时前
C++ 单例模式:饿汉模式与懒汉模式
c++·单例模式·设计模式·饿汉模式·懒汉模式
电商API&Tina1 小时前
淘宝 / 京东关键词搜索 API 接入与实战用途教程|从 0 到 1 搭建电商选品 / 比价 / 爬虫替代系统
java·开发语言·数据库·c++·python·spring
初圣魔门首席弟子1 小时前
Doxygen 文档注释详细介绍(含实际案例)
c++