Подтвердить что ты не робот

Переместить конструкторы и `std:: array`

Согласно N3485 §23.3.2.2:

(...) неявный механизм перемещения и оператор назначения перемещения для массива требуют, чтобы T было MoveConstructible или MoveAssignable соответственно.

Итак, std::array поддерживает перемещение семантики, если тип его элементов. Отлично!

Однако, что это значит? Я склонен представить этот тип как более безопасную версию массива, предоставляющую интерфейс, совместимый с STL, но если это правда, то как std::array перемещать-строить свои элементы? Могу ли я сделать то же самое с обычным массивом?

4b9b3361

Ответ 1

Однако, что это значит?

Это означает, что если тип элемента является подвижным, то и тип массива.

std::array<movable, 42> move_from = {...};
std::array<movable, 42> move_to = std::move(move_from); // moves all the elements

Я склонен представить этот тип как более безопасную версию массива, предоставляющую интерфейс, совместимый с STL

Не совсем. Это оболочка для массива, предоставляющая ему ту же семантику, что и совокупный класс, включая возможность копирования и перемещения.

как std::array перемещать-конструировать свои элементы?

Точно так же, как и любой другой агрегат. Его неявный move-constructor будет перемещать-строить все его элементы, включая элементы любых массивов-членов.

Могу ли я сделать то же самое с обычным массивом?

Только если вы завернете его в тип класса, как это делает std::array.

Ответ 2

Перемещение a std::array отличается от перемещения a std::vector. При перемещении одного std::vector в другое, он (иногда *) позволяет просто переназначить внутренние указатели и вообще не манипулировать элементами.

С std::array это, конечно, невозможно - его элементы имеют автоматическую продолжительность хранения, они буквально содержатся внутри объекта. Тем не менее, каждый отдельный из них все еще может быть перемещен и что операции перемещения на std::array делают **.

* Предполагая, что распределители совместимы и не запрещают эту операцию

** Это также то, что вы получаете с помощью std::vector, когда буфер не может быть повторно использован целевым вектором.

Ответ 3

Конструктор перемещения по умолчанию для (неединичного) класса выполняет поэтапный ход. Перемещение элемента данных необработанного массива означает перемещение каждого из элементов массива, см. [Class.copy]/15.

Следовательно, вы можете перемещать необработанный массив, помещая его внутри класса:

struct wrap
{
    std::string arr[25];
};

auto w = wrap();
auto m = std::move(w); // moves the 25 `std::string`s

Вы также можете вручную вызвать конструктор перемещения элементов, например:

std::string a[3] = { /*...*/ };
std::string b[3] = {std::move(a[0]), std::move(a[1]), std::move(a[2])};

Не указывается, если std::array содержит необработанный массив. Однако он содержит элементы данных value_type, так как он гарантированно является совокупностью. Эти элементы данных будут перемещены, как описано выше, при вызове конструктора перемещения.

Если члены данных из std::array не являются MoveConstructible, то создается экземпляр его конструктора перемещения.