【发布时间】:2016-04-04 14:26:50
【问题描述】:
我正在尝试了解移动构造函数的实现。 我们都知道,如果我们需要在 C++ 类中管理资源,我们需要实现五法则(C++ 编程)。
微软给我们举了一个例子:https://msdn.microsoft.com/en-us/library/dd293665.aspx
这里更好,它使用复制交换来避免代码重复: Dynamically allocating an array of objects
// C++11
A(A&& src) noexcept
: mSize(0)
, mArray(NULL)
{
// Can we write src.swap(*this);
// or (*this).swap(src);
(*this) = std::move(src); // Implements in terms of assignment
}
在move-constructor中,直接:
// Can we write src.swap(*this);
// or (*this).swap(src);
因为我认为(*this) = std::move(src) 有点复杂。因为如果我们不小心写成(*this) = src,它会调用普通的赋值运算符而不是move-assignment-operator。
除了这个问题,在微软的例子中,他们写了这样的代码:在move-assignment-operator中,我们需要检查自赋值吗?有可能发生吗?
// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other)
{
std::cout << "In operator=(MemoryBlock&&). length = "
<< other._length << "." << std::endl;
if (this != &other)
{
// Free the existing resource.
delete[] _data;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}
return *this;
}
【问题讨论】:
-
移动构造函数对我来说似乎很愚蠢。为什么不只是初始化初始化列表中的所有内容,然后将
src设置为有效的从状态移动?如果您不关心更改已移动对象的大小,则最多应为 4 个分配和 3 个。 -
In the move-constructor, directly: // Can we write src.swap(*this); // or (*this).swap(src);我不明白为什么不这样做,假设您实现了合适的swap方法。 -
自移动分配有时会发生,特别是在执行
swap(*it1, *it2)的排序算法中,两个迭代器可能会引用同一个元素,这会进行自交换,可能导致一个自我移动。如果您重载了swap(MemoryBlock&, MemoryBlock&),那么这应该不是问题,将调用您的专用交换而不是std::swap。否则不应该发生自移动,尽管理论上它仍然是可能的。 -
@JonathanWakely 有趣的是,我从来没有在赋值运算符中检查过
this == &other,因为我认为自赋值只会发生错误,并且不应该掩盖错误,而是尽快发现错误。 -
@MaximEgorushkin:我忘了链接到wg21.link/lwg2468
标签: c++ c++11 move move-constructor