Должны ли конструкторы перемещения быть исключениями?
Я читал несколько противоречивых статей в отношении того, разрешено ли бросать конструкторы / присваивания перемещения.
Поэтому я хотел бы спросить, могут ли конструкторы / присваивания перемещений добавляться в окончательный стандарт C++11?
1 ответ
Разрешено ли бросать конструкторам перемещения? Да. Должны ли они? Нет.
В общем, ничто из того, что вы делаете внутри них, не должно быть чем-то, что может бросить. Вы не должны выделять память, вызывать другой код или что-то в этом роде. Единственная причина написать конструктор перемещения - скрыться с чужими указателями памяти и ссылками на объекты. Вы должны скопировать несколько основных типов и обнулить значения в другом объекте. Эти вещи не должны бросать.
Так что, хотя это разрешено, это не очень хорошая идея. Если вы делаете это, переосмыслите то, что вы делаете в своих операциях перемещения.
Вот, чтобы пролить свет на это.
Кажется, что std::vector, в частности, придирчив к тому, объявляете ли вы свои конструкторы перемещения с помощью noexcept. Если вы это сделаете, то их будет использовать std::vector. Если вы этого не сделаете, std::vector вместо этого прибегнет к использованию вашего конструктора копирования. По крайней мере, в некоторых случаях. В частности, всякий раз, когда происходит внутренняя перестановка элементов после изменения размера внутреннего массива.
Вы можете увидеть эффекты в этом примере, где noexcept не объявлено:
http://coliru.stacked-crooked.com/a/285cd07a9a52da3b
И в этом примере, где это:
http://coliru.stacked-crooked.com/a/d043774ec4c279ec
В первом примере std::vector использует конструктор копирования уже при второй и третьей вставке с push_back. Во втором примере он выполняет ту же операцию, но с конструктором перемещения.