c++ - 为什么 C++11 对值参数有隐式 move ,但对右值参数没有?

标签 c++ c++11 move-semantics rvalue-reference c++20

在 C++11 中,值参数(和其他值)在返回时享受隐式 move :

A func(A a) {
    return a; // uses A::A(A&&) if it exists
}

至少在MSVC 2010中,右值引用参数需要std::move:

A func(A && a) {
    return a; // uses A::A(A const&) even if A::A(A&&) exists
}

我想在函数内部,右值引用和值的行为相似,唯一的区别是在值的情况下,函数本身负责销毁,而对于右值引用,责任在外部。

在标准中区别对待它们的动机是什么?

最佳答案

标准化委员会付出了巨大的努力来创建措辞,以便只在两种情况下才会采取行动:

  1. 明显安全的情况下这样做。
  2. 当用户明确询问时(通过 std::move 或类似的类型转换)。

值参数无疑会在函数结束时被销毁。因此,通过 move 将其返回显然是安全的;返回后其他代码无法触及它(除非您故意尝试破坏事物,否则您可能会触发未定义的行为)。因此,它可以从返回中移出。

一个 &&变量可能指的是临时的。但它可能指的是一个左值(一个命名变量)。因此,离开它显然是不安全的;原始变量可能潜伏在周围。而且由于您没有明确要求从它 move (即:您没有在此函数中调用 std::move),因此不会发生 move 。

唯一的一次&&当您 return 时,变量将被隐式 move (即:没有 std::move )。 std::move<T>返回 T&& .该返回值调用 move 构造函数是合法的,因为它是一个返回值。

现在打电话很困难A func(A &&a)有一个左值没有调用std::move (或等效的类型转换)。所以从技术上讲,它 应该 适合 && 的参数要隐式 move 的类型。但标准委员会希望对 && 采取明确的行动。类型,只是为了确保 move 不会在此函数的范围内隐式发生。也就是说,它不能使用关于 && 位置的函数外知识。来自。

一般情况下,您应该只使用 && 的参数。在两种情况下:要么您正在编写 move 构造函数(或 move 赋值运算符,但即使这也可以通过值完成),或者您正在编写转发函数。可能还有其他几种情况,但你不应该采取&&除非你有特别的想法。如果 A是可 move 的类型,那么就按值取吧。

关于c++ - 为什么 C++11 对值参数有隐式 move ,但对右值参数没有?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9779079/

相关文章:

c++ - 预解析(缓存)printf 风格的格式化字符串

c++ - 嵌套的 if-else 不适用于自定义结构 c++

c++ - 根据模板值确定的静态数组大小

c++ - MSVC 错误 - 错误 C2373 : 'description' : redefinition; different type modifiers

c++ - 如果右值引用超出范围会怎样?

c++ - 如何使用基于范围的 for 循环遍历本身是 JSON 数组的 Rapidjson 文档?

c++ - 在 Windows Mobile 上监控存储空间

c++ - 既然我们已经有了 move 语义,那么专门化 std::swap 了吗?

c++ - 默认 move 构造函数中的赋值顺序是什么?

c++ - 使 : *** No targets specified and no makefile found. 停止。 [Ubuntu]