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

Behavioral differences with std::move(*this) from a member function

本文关键字:this 函数 std move 成员      更新时间:2023-10-16

给定类定义:

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()的用例可能是什么。

std::move

"做"任何事情。它所做的只是将左值转换为右值。例:

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