通常说在C ++ 11中按值返回std::vector
是明智的。
在C ++ 03中,这主要是正确的,因为RVO应该优化副本。但是应该让大多数开发人员感到害怕。
std::vector
局部变量吗? 答案 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 ]
如果该向量是局部变量的成员而不是局部变量本身怎么办?
不会尝试移动子对象,因为它不符合复制省略的标准。 (这是愚蠢的,恕我直言,但这就是目前的情况。我不认为这两者应该联系在一起,因为如果它是本地的,子对象可以完全被移动。)
显然,不会移动返回全局变量。还有什么其他案例不会被移动?
显然不会移动引用。除此之外,我无法想到其他任何事情。