【问题标题】:Behavioral differences with std::move(*this) from a member function成员函数与 std::move(*this) 的行为差异
【发布时间】:2017-03-19 23:09:02
【问题描述】:

给定类定义:

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 所做的事情的直觉是什么?也许是错的。 std::move 没有任何事情,它只是一个演员表。
  • 在第一种情况下m1 的类型应该是MoveOnly &amp;&amp;。该值永远不会移动到任何地方。
  • 是的,我正在慢慢接受std::move 实际上并没有做任何事情的事实。这篇文章帮助我澄清了很多事情:jlebar.com/2016/5/28/…

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 2016-07-08
    • 2014-01-09
    • 2022-01-12
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多