如果在将变量传递给函数后我没有使用变量,是否将其传递给非常量左值引用或使用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
答案 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.
希望有所帮助。