人们常说,在 C++11 中std::vector
按值返回是明智的。
在 C++03 中这主要是正确的,因为 RVO 应该优化掉副本。但这应该会吓跑大多数开发人员。
- 在 C++11 中,返回的
std::vector
局部变量是否总是被移动? - 如果该向量是局部变量的成员而不是局部变量本身怎么办?
- 显然返回一个全局变量不会被移动。还有哪些情况不会被移动?
人们常说,在 C++11 中std::vector
按值返回是明智的。
在 C++03 中这主要是正确的,因为 RVO 应该优化掉副本。但这应该会吓跑大多数开发人员。
std::vector
局部变量是否总是被移动? 首先,以前每次可以省略副本,现在仍然可以省略,在相同的情况下可以省略移动。对于本文的其余部分,我将假设由于某种原因不会发生省略(假设编译器编写者很懒惰)。
在 C++11 中,返回的 std::vector 局部变量是否总是被移动?
每次满足复制省略的标准,或者变量是明确的std::move
d。
如果该向量是局部变量的成员而不是局部变量本身怎么办?
它不会被移动,除非明确std::move
d。
显然返回一个全局变量不会被移动。还有哪些情况不会被移动?
每次不满足复制省略的标准并且变量没有明确表示时std::move
d。
这些都不是不按价值返回的正当理由。按值返回是可以的,因为即使没有自动移动值,您也可以使用std::move
.
在 C++11 中,返回的
std::vector
局部变量是否总是被移动?
对于局部变量,即使是按值参数,编译器必须始终尝试首先移动它(如果无论出于何种原因移动和复制都不能被省略,即使满足条件)。如果失败,它会再次尝试复制:
§12.8 [class.copy] p32
当满足或将满足复制操作的省略标准时,除了源对象是函数参数的事实,并且要复制的对象由左值指定时,选择复制的构造函数的重载决策是首先执行好像对象是由 rvalue 指定的。如果重载决议失败,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是 cv 限定的),则再次执行重载决议,将对象视为左值。[注:无论是否会发生复制删除,都必须执行此两阶段重载解决方案。它确定如果不执行省略则要调用的构造函数,并且即使调用被省略,所选构造函数也必须是可访问的。——尾注]
如果该向量是局部变量的成员而不是局部变量本身怎么办?
不会尝试移动子对象,因为它不符合复制省略的标准。(这是愚蠢的,恕我直言,但这就是目前的情况。我认为这两者不应该联系起来,因为如果子对象是本地的,则可以很好地移动它。)
显然返回一个全局变量不会被移动。还有哪些情况不会被移动?
引用显然不会被移动。除此之外,我真的想不出别的了。