Ответ 1
Вот рекомендуемый шаблон:
array2D(array2D&& that)
: data_(std::move(that.data_)),
height_(std::move(that.height_)),
width_(std::move(that.width_)),
size_(std::move(that.size_))
{
that.data_ = 0;
that.height_ = 0;
that.width_ = 0;
that.size_ = 0;
}
Естественно, если члены данных являются скалярными типами, std::move
не требуется. Но если вы копируете этот шаблон вокруг, полезно включить move
так или иначе, чтобы, когда данные элемента не являются скалярными, std::move
не забывается.
Кроме того, если данные элемента имеют фактические конструкторы перемещения, вы можете просто опустить тело:
array2D(array2D&& that)
: data_(std::move(that.data_)),
height_(std::move(that.height_)),
width_(std::move(that.width_)),
size_(std::move(that.size_))
{
}
И если вы хотите обобщить типы, у которых нет конструкторов перемещения, но они имеют состояние по умолчанию, не основанное на ресурсах, вы можете:
array2D(array2D&& that)
: data_(std::move(that.data_)),
height_(std::move(that.height_)),
width_(std::move(that.width_)),
size_(std::move(that.size_))
{
that.data_ = Data();
that.height_ = Height();
that.width_ = Width();
that.size_ = Size();
}
Я рекомендую упорядочить эти операторы в том же порядке, в котором они объявлены как члены данных в определении класса array2D
. И я не нахожу ничего плохого в повторении списка инициализаторов в теле. Это необходимый и второй шаг. Нет необходимости подметать его под ковром.