Возможно ли иметь типы с операциями перемещения, которые выбрасывают контейнеры? - PullRequest
0 голосов
/ 29 мая 2018

Объясняя операции перемещения над объектами с коллегой, я в основном говорил, что операции перемещения не должны вызывать исключения в контейнере, потому что если операция перемещения завершается неудачей, то нет способа надежно вернуть исходный объект.Думая об этом больше, мне интересно, если это не правильно, и что если операция перемещения, которая бросает, он может вернуть исходный объект обратно в исходное состояние.

Причина этого заключается в том, что еслиобъект может сгенерировать, тогда он сгенерирует не копирование или перемещение содержащихся объектов со старого на новый адрес, а выброс, если ресурс не был получен.Так что вся оригинальная информация все еще должна быть там.Если это так, то должен ли компилятор не иметь возможности отменить операции, которые он выполнял для восстановления исходного объекта?

Возможно, что операция может быть односторонней, как перемещение целого числа, нов этом случае он может просто завершить работу приложения, и, возможно, если бы разработчик хотел избежать односторонней операции, вместо этого мог бы использовать метод подкачки.

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

Я упрощаю вещи?Есть ли что-то, что я пропустил, что удерживает контейнеры от движущихся объектов без конструктора / оператора перемещения без бросков?

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Прежде всего, я с трудом представляю объект, который получает ресурсы в операции перемещения.Подумайте об этом - unique_ptr просто передает указатель, не получая ничего, то же самое для shared_ptr.string, vector, все контейнеры и т. Д. Просто крадут указатели на ресурсы, полученные ранее в конструкторе по умолчанию или в конструкторе копирования.Я чувствую, что бросать из конструктора движения - это как бросать из деструктора.Конечно, давай, стреляй себе в колено.Но хорошо, я могу принять, что исключения из этого существуют.

Итак, давайте перейдем ко второй точке - при перемещении может быть момент, когда фактически оба объекта (перемещенные и перемещенные) недопустимы.А для отката из такой ситуации потребуется дополнительная «магическая» функция, чтобы исправить одну из них.Таким образом, кажется, что данные не могут быть восстановлены, так как стандарт не определяет такую ​​функцию.

0 голосов
/ 29 мая 2018

Вы можете использовать типы с бросками в контейнерах, таких как vector, которые могут перемещать свои элементы.Однако такие контейнеры не будут использовать операции броска.

Допустим, у вас есть vector из 10 элементов броска.И vector должен изменить свой размер.Таким образом, он перемещает 5 объектов в новую память, но 6-й бросок.Ну, все в порядке;Строительство не удалось, поэтому предположение, что стоимость 6-го объекта в порядке.То есть, какой бы ни была гарантия исключения этого типа, будет то, как все будет работать.

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

C ++ в общем случае не имеет правильных ответов, когда сам процесс восстановления неисправности завершается неудачно.Вы можете видеть это в исключениях;вы не можете создать исключение из деструктора, который вызывается в процессе разматывания из-за сбоя исключения.std::terminate происходит в этом случае.

То же самое относится и к vector.Если возвращение не удастся, vector не имеет вменяемого ответа.Таким образом, если vector не может гарантировать , что восстановление его предыдущего состояния массива равно noexcept, то оно будет использовать копирование, поскольку это может обеспечить такую ​​гарантию.

...