【发布时间】: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 &&。该值永远不会移动到任何地方。 -
是的,我正在慢慢接受
std::move实际上并没有做任何事情的事实。这篇文章帮助我澄清了很多事情:jlebar.com/2016/5/28/…
标签: c++ c++11 move-semantics rvalue-reference