0Pricing
C++ Academy · 课时

std::move 与 std::forward

使用 std::move 将左值转换为右值,并使用 std::forward 保留值类别

std::move 与 std::forward 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

两个近亲,各司其职

std::move 和 std::forward 都是编译期类型转换。它们看起来相似,但解决的是不同的问题。

std::move:始终转换为右值

std::move(x) 无条件地将 x 转换为右值引用。接收方函数随后就可以窃取它的资源。

std::string s = "Hello";
std::string t = std::move(s);   // move-constructs t from s
// s is now in a valid-but-unspecified state

何时使用 move

请在以下场景中使用 std::move:

  • 移动构造函数和移动赋值运算符
  • 当您想强制移动时返回局部变量(很少需要这样做——RVO 通常会生效)
  • 将不再需要的局部对象传给接收函数

std::move 的实现

它只是伪装成其他形式的 static_cast:

template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}

std::forward:保留值类别

在使用转发引用(T&&)的模板中,std::forward<T>(x) 会将 x 转换回其原始值类别(左值或右值)。它用于完美转发。

template <typename T>
void wrapper(T&& arg) {
    target(std::forward<T>(arg));  // forwards as lvalue or rvalue depending on T
}

为什么需要转发

在模板内部,参数拥有一个名称,因此会成为左值,即使调用者传入的是右值。std::forward 可以恢复原始值类别。

不使用 std::forward

如果不使用 forward,所有参数都会在 wrapper 内部作为左值传递,从而无法实现调用者所希望的移动语义。

template <typename T>
void wrapper(T&& arg) {
    target(arg);    // always lvalue — wrong
}

始终为 forward 指定模板参数

std::forward<T> 要求显式提供模板参数。如果省略该参数,行为就会不正确。

完美转发示例

能够转发构造函数参数的工厂函数可以保留右值与左值之间的区别,从而提高效率。

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

只移动一次

每个对象最多应被移动一次。移动之后,对象处于有效但未指定的状态——通常应重新赋值或销毁它。在重新赋值之前使用已被移动的对象,可能会导致难以察觉的错误。

经验法则

快速的思维模型:

  • 有一个具体类型,并希望移动它 → std::move
  • 有一个模板参数,并希望保留值类别 → std::forward<T>

快速检查

在参数为 T&& arg 的模板函数内部,如何在保留 arg 左值或右值类别的同时转发它?

回顾

std::move 无条件地将对象转换为右值——用于您想从中窃取资源的具体对象。std::forward<T> 会在通用模板内部保留值类别——用于完美转发。

常见问题解答

「std::move 与 std::forward」课时是免费的吗?

是的 — 「std::move 与 std::forward」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「std::move 与 std::forward」这节课中我会学到什么?

使用 std::move 将左值转换为右值,并使用 std::forward 保留值类别 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「std::move 与 std::forward」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 左值与右值:区别所在
  2. 右值引用与 && 语法
  3. std::move 与 std::forward
  4. 移动构造函数与移动赋值
← 返回 C++ Academy