Идиоматический способ реализации операций перемещения в классах со стандартным элементом-контейнером не может быть noexcept
и, следовательно, не может быть перемещен с помощью таких операций, как vector.push_back()
. Или я ошибаюсь?
Чтобы получить скорость от
vector<Elem> data;
// ...
data.push_back( elem );
Мы рекомендуем выполнять операции перемещения noexcept
-- чтобы во время изменения размера векторов библиотека могла безопасно перемещать элементы в перераспределенное хранилище.
class Elem {
// ...
Elem(Elem&&) noexcept; // noexcept important for move
Elem& operator=(Elem&&) noexcept; // noexcept important for move
};
Пока все хорошо, теперь мои elem
можно отталкивать гораздо быстрее.
Но: если я добавлю контейнер в качестве члена, может ли мой класс по-прежнему быть помечен как noexcept-move? Все стандартные контейнеры не имеют ход noexcept
!
class Stuff {
vector<int> bulk;
// ...
Stuff(Stuff&& o) // !!! no noexcept because of vector-move
: bulk(move(o.bulk))
{}
Stuff& operator=(Stuff&&) // !!! no noexcept...
{ /* appropriate implementation */ }
};
Это также означает, что мы также не можем полагаться на сгенерированные компилятором операции перемещения, верно? Следующий полный класс также не будет иметь noexcept
-операций перемещения и, следовательно, не будет «быстрым», верно?
struct Holder {
vector<int> bulk;
};
Возможно, vector<int>
слишком просто перемещать, но как насчет vector<Elem>
?
Это имело бы серьезные последствия для всех структур данных с контейнерами в качестве членов.
std::vector::swap()
может быть иnoexcept
. - person woolstar   schedule 24.01.2014