Семантика перемещения заменяет семантику копирования в ситуациях, когда копирование неэффективно. Семантика копирования имеет дело полностью с копируемыми объектами, включая объекты const.
В c ++ 11 уже существует множество не копируемых объектов, например std :: unique_ptr. Эти объекты полностью полагаются на семантику перемещения, потому что перемещение от объекта позволяет сделать его недействительным. Это важно (imho) для популярных шаблонов дизайна, таких как RAII.
Проблема возникает, когда постоянный не копируемый объект назначается области памяти. Такой объект никак нельзя восстановить.
Это очевидно важно в течение жизни объекта из-за его постоянства. Однако в конце своего жизненного цикла, когда вызывается деструктор, (несуществующий) объект ненадолго не является константным.
Я полагаю, что перемещение Деструктор может быть ценным дополнением к модели семантики перемещения.
Рассмотрим простую ситуацию, когда unique_ptr используется в unordered_set. Вы можете insert
в этот набор, используя конструктор перемещения (или конструкцию «emplace»), однако, если вы захотите переместить этот указатель на другой unordered_set (то есть, оставив его постоянным), это будет невозможно.
Существенный, есть iterator insert((possibly const) key&&)
но нет const key&& erase(iterator)
, На самом деле это было бы невозможно. Контейнер может быть расширен только для того, чтобы вернуть некоторый указатель на ключ и забыть о нем.
Движущийся деструктор может решить эту проблему, т.е. const MyClass&& ~MyClass()
, поскольку он будет нарушать только const во время уничтожения (когда компилятор считает объект недействительным в любом случае).
РЕДАКТИРОВАТЬ: я должен указатьconst MyClass&& ~MyClass() const
на самом деле имеет больше смысла. Деструктор не должен изменять ничего, только уничтожать объект, как если бы он больше не был действительным дескриптором любого ресурса, которым он управлял.
Имхо вы определили реальную потребность.
Ваше решение очень похоже на то, что я назвал семантика разрушительного движения. Эта возможность описана в оригинальное предложение семантики хода. Я думаю, что такой дизайн возможен, хотя и не без проблем. Насколько я знаю, никто не занимается этой областью в комитете по стандартам.
Существуют более простые способы извлечения типов перемещения только из ассоциативных контейнеров, которые не требуют языковых изменений (кроме, возможно, разрешения наложения типов без неопределенного поведения).
N3645 это предложение только для библиотеки, которое помещает вложенный node_ptr
введите в каждый контейнер. node_ptr
очень похоже на unique_ptr
, Он имеет уникальное право собственности на узел в ассоциативном контейнере. Но когда вы разыменовываете его, вы получаете неконстантный доступ к value_type
в узле, а не сам узел. extract
а также insert
элементы добавляются в ассоциативные контейнеры, позволяющие вставлять и удалять узлы (принадлежащие node_ptr
) в / из контейнеров.
Вы можете использовать это, чтобы удалить узел из контейнера, а затем переместить тип только для перемещения из узла и позволить ~node_ptr()
очистите узел, когда вы закончите с ним. Документ включает в себя этот пример, чтобы продемонстрировать эту функциональность:
set<move_only_type> s;
s.emplace(...);
move_only_type mot = move(*s.extract(s.begin())); // extract, move, deallocate node
Обратите внимание, что s.extract
является noexcept
, как есть ~node_ptr()
конечно. Если двигаться строительство move_only_type
является noexcept
тогда вся эта операция noexcept
, В противном случае, если конструкция хода сработает, set
остается, как если бы элемент был удален из set
,
На данный момент никакого прогресса не достигнуто N3645. За него не проголосовали в рабочем проекте, и я не уверен, что это когда-либо будет.
Обновление C ++ 17
Я исправлен: функциональность, которую я описал выше, была выбрана в C ++ 17 с P0083R3. Спасибо Cosme за напоминание об этом в комментариях ниже.
Извините, но предпосылка ошибочна.
unordered_set
на самом деле не держит const
объекты. Это просто не дает вам права на запись для содержащихся элементов. Это свойство только принадлежностей.
Можно было бы добавить key erase(iterator)
функция, которая просто перемещает элемент во временный. Я не уверен, почему вы хотите key&&
там.
Что касается const MyClass&& ~MyClass() const
Это не имеет смысла по трем причинам: у dtors нет ни типов возврата, ни классификации CV, ни разрешение перегрузки для них.
Итак, в основном вы говорите, что должно быть возможно переместить const
возражать в другое const
возразить и уничтожить оригинал?
Извините, но я думаю, что весь точка сделать это const
это предотвратить это.
Иначе это образовало бы лазейку: вы могли бы уничтожить const
объект из своей памяти, то вы уничтожаете другой const
объект в ячейку памяти первого (через размещение new
).
Теперь объект имеет изменено хотя это было const
… так по существу const
был бесполезен.
Смотрите комментарии ниже …