鉴于课程定义:
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()
的不同版本的用例可能是什么。
答案 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