传递右值引用与非const左值引用

时间:2013-12-15 06:47:01

标签: c++ c++11 move-semantics rvalue-reference

如果在将变量传递给函数后我没有使用变量,是否将其传递给非常量左值引用或使用std :: move将其传递给右值引用是否重要。假设有两种不同的重载。这两种情况的唯一区别是传递对象的生命周期,如果我通过右值引用,则会提前结束。还有其他因素需要考虑吗?

如果我有一个函数foo重载像:

void foo(X& x);
void foo(X&& x);

X x;
foo(std::move(x));   // Does it matter if I called foo(x) instead?
// ... no further accesses to x
// end-of-scope

2 个答案:

答案 0 :(得分:1)

当通过右值引用传递时,对象的生命周期不会结束。右值引用仅允许foo权限获取其参数的所有权,并可能将其值更改为无意义。这可能涉及解除分配其成员,这是生命的终结,但论证本身就在其声明范围的终点。

在上次访问时使用std::move是惯用的。没有潜在的缺点。据推测,如果有两个重载,则右值引用具有相同的语义但效率更高。当然,他们可以做完全不同的事情,只是为了疯狂的虐待狂。

答案 1 :(得分:1)

这取决于您在foo()中的行为:

  • foo()内,如果您将参数存储在某个内部存储中,那么从可读性的角度看它是否重要,因为它在呼叫站点是显式的这个特定的参数被移动,并且在函数调用返回后不应该在调用站点使用它。

  • 如果您只是读取/写入其值,那么无关紧要。请注意,即使您通过T&,参数仍然可以移动到某个内部存储,但这不是首选方法 - 实际上它应该被认为是一种危险的方法。

另请注意,std::move实际上移动对象。它只是使对象可移动。如果对象调用move-constructor或move-assignment:

,则移动该对象
void f(X && x) { return; }
void g(X x) { return; }

X x1,x2;
f(std::move(x1)); //x1 is NOT actually moved (no move constructor invocation).
g(std::move(x2)); //x2 is actually moved (by the move-constructor).

//here it is safe to use x1
//here it is unsafe to use x2

好吧,它比这更复杂。考虑另一个例子:

void f(X && x) { vec_storage.push_back(std::move(x)); return; }
void g(X x) { return; }

X x1,x2;
f(std::move(x1)); //x1 is actually moved (move-constructor invocation in push_back)
g(std::move(x2)); //x2 is actually moved (move-constructor invocation when passing argument by copy).

//here it is unsafe to use x1 and x2 both.

希望有所帮助。