按值返回std :: vector

时间:2012-06-28 15:14:06

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

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

在C ++ 03中,这主要是正确的,因为RVO应该优化副本。但是应该让大多数开发人员感到害怕。

  • 在C ++ 11中,将始终移动返回的std::vector局部变量吗?
  • 如果该向量是局部变量的成员而不是局部变量本身怎么办?
  • 显然不会移动返回全局变量。还有什么其他案例不会被移动?

2 个答案:

答案 0 :(得分:15)

首先,每次复制之前都可以省略,现在仍然可以省略,并且可以在相同的情况下省略移动。对于这篇文章的其余部分,我将假设elision不会因某种原因发生(假装编译器编写者在某种程度上是懒惰的。)

  

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

每次满足复制省略的标准,或者变量明确std::move d。

  

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

除非明确std::move d。

,否则不会移动它
  

显然,不会移动返回全局变量。还有什么其他案例不会被移动?

每次不符合复制条件的标准且变量未明确std::move d。

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

答案 1 :(得分:8)

  

在C ++ 11中,将始终移动返回的std::vector局部变量吗?

对于局部变量,甚至是按值参数,编译器必须始终尝试首先移动它(如果移动和副本都不能因任何原因被删除,即使标准得到满足)。如果失败,它会再次尝试复制:

§12.8 [class.copy] p32

  

当满足或将满足复制操作的省略标准时,除了源对象是函数参数之外,并且要复制的对象由左值指定,重载决策要选择首先执行副本的构造函数,就像对象是由右值指定的一样。如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值。 [注意:无论是否发生复制省略,都必须执行此两阶段重载决策。如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数。 -end note ]

     

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

不会尝试移动子对象,因为它不符合复制省略的标准。 (这是愚蠢的,恕我直言,但这就是目前的情况。我不认为这两者应该联系在一起,因为如果它是本地的,子对象可以完全被移动。)

  

显然,不会移动返回全局变量。还有什么其他案例不会被移动?

显然不会移动引用。除此之外,我无法想到其他任何事情。