从函数返回值以避免复制时使用std :: move() [英] Using std::move() when returning a value from a function to avoid to copy
问题描述
考虑支持默认移动语义的T类型。还考虑下面的函数:
Consider a type T supporting the default move semantics. Also consider the function below:
T f() {
T t;
return t;
}
T o = f();
在旧的C ++ 03中,某些非最佳编译器可能会两次调用复制构造函数,一个
In the old C++03, some non-optimal compilers might call the copy constructor twice, one for the "return object" and one for o
.
在c ++ 11中,因为<$ c $是一个返回对象,另一个是 o
。 f()
中的c> t 是一个左值,这些编译器可能会像以前一样调用一次拷贝构造函数,然后为o。
In c++11, since t
inside f()
is an lvalue, those compilers might call the copy constructor one time as before, and then call the move constructor for o.
是否正确地声明避免第一个额外副本的唯一方法是移动 t
当返回时?
Is it correct to state that the only way to avoid the first "extra copy" is to move t
when returning?
T f() {
T t;
return std::move(t);
}
推荐答案
否。每当 return
语句中的局部变量有资格进行复制省略时,它会绑定到右值re fe rence,因此 return t;
在您的示例中与 return std :: move(t);
相同,即符合条件的构造函数。
No. Whenever a local variable in a return
statement is eligible for copy elision, it binds to an rvalue reference, and thus return t;
is identical to return std::move(t);
in your example with respect to which constructors are eligible.
但是请注意,返回std :: move(t);
防止编译器执行复制省略,而返回t
;不需要,因此后者是首选样式。 [感谢@Johannes提供的校正。]如果发生复制省略,则是否使用移动构造的问题将成为讨论的重点。
Note however that return std::move(t);
prevents the compiler from exercising copy elision, while return t
; does not, and thus the latter is the preferred style. [Thanks to @Johannes for the correction.] If copy elision happens, the question of whether or not move construction is used becomes a moot point.
请参见在标准中为12.8(31,32)。
See 12.8(31, 32) in the standard.
还请注意,如果 T
具有可访问的副本,但删除move构造函数,然后返回t;
将不会编译,因为必须首先考虑move构造函数;您必须说出 return static_cast< T&>(t);
的效果才能使它起作用:
Note also that if T
has an accessible copy- but a deleted move-constructor, then return t;
will not compile, because the move constructor must be considered first; you'd have to say something to the effect of return static_cast<T&>(t);
to make it work:
T f()
{
T t;
return t; // most likely elided entirely
return std::move(t); // uses T::T(T &&) if defined; error if deleted or inaccessible
return static_cast<T&>(t) // uses T::T(T const &)
}
这篇关于从函数返回值以避免复制时使用std :: move()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!