【问题标题】:C++11 implicit move constructorsC++11 隐式移动构造函数
【发布时间】:2014-04-05 22:33:11
【问题描述】:

我无法理解为什么以下内容(至少根据 gcc 4.8)在 C++11 中是合法的:

// This class manages a non-copyable resource.
struct B {
  B();
  B(B &&) { /* logging, etc., to verify if needed. */ }
private:
  B(B const &);
  B const &operator=(B const &);
};

B bar() {
  B b;
  // This is apparently allowed via the move constructor.
  return b;
};

int main() {
  // From this "side" of the call as well.
  B b1 = bar();
  B b2{bar()};
}

在哪些情况下语言允许或实际首选移动构造函数?临时返回值似乎可以移动(和垃圾内容),但我想为所有可以静默使用移动的地方找到核心语言规则。谢谢!

【问题讨论】:

  • 首先,有一个不错的新delete关键字:en.wikipedia.org/wiki/…
  • “但我想为所有可以静默使用移动的地方找到核心语言规则”没有一个 规则,但有几个。 “最晦涩的”是返回一个局部变量/一个参数,有一定的限制。除此之外,右值会被移动(您需要查看 C++11 中的右值是什么)。
  • @dyp 您是否碰巧至少有方便的规范通用部分?只要不是盲目搜索,我愿意大量阅读。
  • @Jeff 我认为第 3 节和第 12 节将介绍 rvalues 如何绑定。我想你可能对prvalues 最感兴趣。
  • @Jeff 正如杰森所说;我将其进一步缩小到 3.10 [basic.lval] 描述 什么是右值,8.5.3./5 [dcl.init.ref] 哪些初始化表达式可以绑定到rvalue、12.8 [class.copy] 何时是隐式生成的移动构造函数 和 12.8/32 返回语句的特殊规则,最后是 13.3.3.2/ 3 [over.ics.rank] rvalue refs 和 const lvalue refs 之间的重载分辨率。这应该涵盖大多数 情况,但可能难以理解。也许阅读一些关于该主题的文章或书籍可能是一个更好的主意。

标签: c++ c++11 object-lifetime move-constructor


【解决方案1】:

只要参数绑定到rvalue 引用,编译器就可以使用移动。只要参数是prvalue,编译器就会使用它(见下文)。参数也可以转换为 rvalue 引用。

通常,右值是指出现在赋值右侧的任何内容。一个粗略的思考方式是看它是否可以在代码中被引用。左值有标识,而右值一般没有。

真的,有几种类型的左值和右值...

  • lvalue - 有身份,不能移动 (lvalue)
  • xvalue - 有身份,可以移动(lvaluervalue
  • prvalue - 没有身份,可以移动 (rvalue)

xvalue 既是 lvalue,又是 rvalue。例如,您使用 std::move 显式转换为 rvalue 引用。

【讨论】:

  • 这里不包括返回值的情况。
  • 返回值取决于调用的上下文。如果你看上面的例子,bar() 返回的值没有标识,并且是可移动的(prvalue)。
  • 嗯,我没有表达清楚,对不起。在返回语句中,命名变量(左值)也可以在一些限制下移动(本质上,它是 NRVO 的替代方案,当 NRVO 本身不能/不应用时。)
  • 确切地说,身份的范围是函数。在调用站点,分配/构造,它没有身份。如果有一个 move-assign B& operator=(B&& b)function,它将为复制和分配移动。
  • 对不起,但我不明白你最后一句话的意思(“如果有一个移动分配......”)。在返回语句的上下文中,具有身份且左值的变量被视为右值以将其移出本地范围。这是一般移动右值但不移动左值的附加规则。
【解决方案2】:

此外,还有一个很好的关于右值引用和移动语义的介绍 http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html

【讨论】:

  • 链接不是答案。链接可以补充答案。
猜你喜欢
  • 2018-01-23
  • 2012-05-11
  • 2020-09-07
  • 2014-02-22
  • 2012-11-09
  • 1970-01-01
  • 2012-10-17
相关资源
最近更新 更多