【问题标题】:Returning std::vector by value按值返回 std::vector
【发布时间】:2012-06-30 03:37:23
【问题描述】:

人们常说,在 C++11 中,按值返回 std::vector 是明智的。

在 C++03 中,这主要是正确的,因为 RVO 应该优化掉副本。但这应该吓跑了大多数开发人员。

  • 在 C++11 中,返回的 std::vector 局部变量是否总是被移动?
  • 如果该向量是局部变量而不是局部变量本身的成员怎么办?
  • 显然不会移动返回的全局变量。还有哪些情况不会搬家?

【问题讨论】:

标签: c++ c++11 return-value move-semantics


【解决方案1】:

首先,以前每次可以省略副本,现在仍然可以省略,并且在相同情况下可以省略动作。对于这篇文章的其余部分,我将假设由于某种原因不会发生省略(假设编译器编写者很懒惰)。

在 C++11 中,返回的 std::vector 局部变量是否总是被移动?

每次满足复制省略的条件,或者变量显式为std::moved。

如果该向量是局部变量的成员而不是局部变量本身呢?

除非明确std::moved,否则它不会被移动。

显然返回一个全局变量不会被移动。还有哪些情况不会搬家?

每次不满足复制省略的条件且变量未明确std::moved。

这些都不是不按值返回的正当理由。按值返回是可以的,因为即使没有自动移动该值,您也可以使用std::move 强制它。

【讨论】:

  • 如果可以 RVO,我认为它不会被移动。
  • @juanchopanza 好吧,是的,这些都不会阻止优化。
  • 好的;您的第一点似乎暗示每次满足复制省略的标准时它移动。
  • @juanchopanza 你是对的。我现在把一切都说清楚了。我认为。
  • 也许我误解了你所说的“复制省略的标准”的意思,但是:ideone.com/QK34O
【解决方案2】:

在 C++11 中,返回的 std::vector 局部变量是否总是被移动?

对于局部变量,即使是按值参数,编译器必须始终尝试首先移动它(如果移动和复制都不能因为某种原因而被忽略,即使符合标准)。如果失败,它会再次尝试复制:

§12.8 [class.copy] p32

当满足或将满足删除复制操作的条件时,除了源对象是函数参数这一事实之外,并且要复制的对象由左值指定,重载决议选择复制的构造函数首先执行,就好像对象是由右值指定的一样。如果重载决议失败,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是 cv 限定的),则再次执行重载决议,将对象视为左值。 [ 注意: 无论是否会发生复制省略,都必须执行此两阶段重载解决方案。它确定如果不执行省略则要调用的构造函数,并且即使调用被省略,所选构造函数也必须是可访问的。 ——尾注 ]

如果该向量是局部变量的成员而不是局部变量本身呢?

不会尝试移动子对象,因为它不符合复制省略的条件。 (恕我直言,这很愚蠢,但目前就是这样。我认为这两者不应该联系起来,因为如果子对象是本地的,则可以很好地移动它。)

显然返回一个全局变量不会被移动。还有哪些情况不会搬家?

一个引用显然不会被移动。除此之外,我真的想不出别的了。

【讨论】:

  • 对本地的引用怎么样?如果在本地 ref 上调用 std::move 会怎样?
  • @deft_code:引用本身不会自动移动,在这方面我的最后一句话似乎不够清楚。 std::move'd 引用将移动被引用的对象。
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2019-02-19
  • 2022-10-21
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多