将对象作为函数的参数发送时移动语义

Rip*_*peR 7 c++ move-constructor move-semantics c++11

我正在玩移动构造函数和移动任务,我偶然发现了这个问题.第一个代码:

#include <iostream>
#include <utility>

class Foo {
    public:
        Foo() {}

        Foo(Foo&& other) {
            value = std::move(other.value);
            other.value = 1; //since it's int!
        }

        int value;

    private:
        Foo(const Foo& other);
};


void Bar(Foo&& x) {
    std::cout << "# " << x.value << std::endl;
}

int main() {
    Foo foo;
    foo.value = 5;

    Bar(std::move(foo));
    std::cout << foo.value << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,当我使用:

Bar(std::move(foo));
Run Code Online (Sandbox Code Playgroud)

程序应该将foo对象"移动"到使用Bar函数中的move构造函数创建的临时对象.这样做会使foo对象的值等于零.不幸的是,它接触Bar函数中作为参数保存的对象是某种参考,因为它不会"移动"原始值,但使用Bar的参数我可以更改它.

有人会介意我为什么在控制台看到我:

#5
5
Run Code Online (Sandbox Code Playgroud)

代替

#5
0 //this should be done by move constructor?
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 18

右值参考确实是(惊喜:) 参考.

可以从它移动,但std::move不能移动.

所以,如果你不从它移动,你实际上将操作rvalue对象(通过右值引用).


通常的模式是

void foo(X&& x)
{
    X mine(std::move(x));

    // x will not be affected anymore
}
Run Code Online (Sandbox Code Playgroud)

但是,当你这样做的时候

void foo(X&& x)
{
    x.stuff();
    x.setBooDitty(42);
}
Run Code Online (Sandbox Code Playgroud)

实际上,X &&只是作为传统参考


vso*_*tco 8

当你写作时,value = std::move(other.value);你应该明白,std::move不会移动任何东西.它只是将其参数转换为右值参考,然后,如果左侧有一个移动构造函数/赋值运算符,左侧将处理它(以及如何实际移动对象).对于普通旧类型(POD),std::move实际上没有做任何事情,因此旧值保持不变.你不是在"身体上"移动任何东西.