首页 文章

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

提问于
浏览
1

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

  • 1

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

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

  • 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.
    

    希望有所帮助 .

相关问题