与成员函数的std :: move(* this)的行为差异

时间:2017-03-19 23:09:03

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

鉴于课程定义:

struct MoveOnly
{
    MoveOnly(int v_)
    : v(v_)
    {
        std::cout << ((void*)this) << " MoveOnly " << v << "\n";
    }

    ~MoveOnly()
    {
        std::cout << ((void*)this) << " ~MoveOnly " << v << "\n";
    }

    MoveOnly(const MoveOnly&) = delete;
    MoveOnly& operator=(const MoveOnly&) = delete;

    MoveOnly(MoveOnly &&src)
    {
        v = std::exchange(src.v, -1);
        std::cout << ((void*)this) << " MoveOnly&& " << v << "\n";
    }

    MoveOnly& operator=(MoveOnly&&) = default;

    MoveOnly&& Apply()
    {
        std::cout << ((void*)this) << " Apply " << v << "\n";
        return std::move(*this);
    }

    int v;
};

控制台显示代码:

auto m1 = MoveOnly(1);
m1.Apply();

> 0x7fff5fbff798 MoveOnly 1
> 0x7fff5fbff798 Apply 1
> 0x7fff5fbff798 ~MoveOnly 1

现在,如果我更改Apply以返回值而不是r值引用:

MoveOnly Apply()
{
    std::cout << ((void*)this) << " Apply " << v << "\n";
    return std::move(*this);
}

我明白了:

auto m1 = MoveOnly(1);
m1.Apply();

> 0x7fff5fbff798 MoveOnly 1
> 0x7fff5fbff798 Apply 1
> 0x7fff5fbff790 MoveOnly&& 1
> 0x7fff5fbff790 ~MoveOnly 1
> 0x7fff5fbff798 ~MoveOnly -1

第一个例子似乎保留了原始对象,这违背了我对std :: move所做的直觉。虽然因为它没有调用移动构造函数,但我可以看到原始对象如何仍然具有1

我在这里要弄清楚的是C ++标准如何解释这种行为以及Apply()的不同版本的用例可能是什么。

1 个答案:

答案 0 :(得分:3)

std::move不会&#34;做&#34;任何东西。它所做的就是将左值投入右值。例如:

class Foo { ... };

void leave(Foo && f) {}

void take(Foo && f) { auto g = std::move(f); }

Foo f;

leave(f); // this won't compile, bar wants an rvalue

leave(std::move(f)); //  this compiles, but f is not changed in any way

take(std::move(f)); // compiles, and leaves f in the moved from state

Apply的原始版本本身并没有做任何事情,但它可以启用其他功能。例如,假设Apply的原始定义:

auto m1 = MoveOnly(1);
m1.Apply(); // does nothing
auto m2 = m1; // doesn't compile
auto m2 = m1.Apply() // Does compile, and does something! moves m1 to m2