为什么 C++ 移动语义离开构造的源代码?

Why does C++ move semantics leave the source constructed?

在 C++11 中,引入了 "move semantics",通过两个特殊成员实现:移动构造函数和移动赋值。这两个操作都离开了 moved-from 构造的对象。

让源处于破坏状态不是更好吗?对于移出的对象,您唯一能做的不就是销毁它吗?

在"universe of move operations"中有四种可能:

target          source
  is            is left
----------------------------------------------------------
constructed <-- constructed  // C++11 -- move construction
constructed <-- destructed
assigned    <-- constructed  // C++11 -- move assignment
assigned    <-- destructed

这些操作中的每一个都是有用的! std::vector<T>::insert 单独使用前三个就可以了。虽然注意:

  • 第二个和第四个源不应该有自动、静态或线程存储持续时间。源的存储持续时间必须是动态的,否则编译器将在已经析构的 object 上调用析构函数。不,编译器不能(通常)跟踪 object 是否已经 moved-from:

X x1, x2;
if (sometimes)
{
    x1 = std::move(x2);
}
// Is x2 moved-from here?

  • 第2个和第4个可以分别被第1个和第3个模拟,只需在操作后手动调用源上的析构函数即可。

  • 第一个和第三个很关键。 std::swapstd::sort 等算法经常需要这两种操作。这些算法不需要破坏它们的任何输入 object——只需更改它们的值。

有了这些知识,在 2001-2002 年的时间范围内,我将精力集中在构建源代码的两个操作上,因为这两个操作会对当时的 C++98 产生最大的(积极的)影响.我当时就知道,如果我不限制这个项目的雄心壮志,它就永远不会成功。即使有所缩减,也很难成功 too-ambitious。

此缩减已在 the original move semantics proposal 标题为 "Destructive move semantics" 的部分下得到承认。

In the end, we simply gave up on this as too much pain for not enough gain. However the current proposal does not prohibit destructive move semantics in the future. It could be done in addition to the non-destructive move semantics outlined in this proposal should someone wish to carry that torch.

有关 moved-from object 的更多详细信息,请参阅 https://whosebug.com/a/7028318/576911