В языке программирования C ++ Edition 4 есть пример векторной реализации, см. Соответствующий код в конце сообщения.
uninitialized_move () инициализирует новые объекты T в новую область памяти, перемещая их из старой области памяти. Затем он вызывает деструктор исходного T-объекта, перемещенного объекта. Почему вызов деструктора необходим в этом случае?
Вот мое неполное понимание: перемещение объекта означает, что право собственности на ресурсы, принадлежащие перемещенному объекту, передается перемещенному объекту. Остатки в объекте move-from являются некоторыми возможными членами встроенных типов, которые не нужно уничтожать, они будут освобождены, когда vector_base b выйдет из области видимости (внутри резерв(), после своп() вызов). Все указатели в объекте move-from должны быть помещены в nullptr, или используется какой-то механизм, чтобы отказаться от владения объектом move-from на этих ресурсах, чтобы мы были в безопасности, тогда зачем вызывать деструктор для истощенного объекта, когда «vector_base b «В любом случае деструктор освободит память после завершения перестановки?
Я понимаю необходимость явного вызова деструктора в тех случаях, когда он должен вызываться, потому что нам есть что разрушить (например, отбрасывать элементы), но я не вижу его значения после std :: move + deallocation из vector_base. Я читаю некоторые тексты в сети и вижу вызов деструктора удаленного объекта как сигнал (кому или чему?), Что время жизни объекта истекло.
Пожалуйста, объясните мне, какую значительную работу предстоит проделать деструктору? Спасибо!
Ниже приведен фрагмент кода http://www.stroustrup.com/4th_printing3.html
template<typename T, typename A>
void vector<T,A>::reserve(size_type newalloc)
{
if (newalloc<=capacity()) return; // never decrease allocation
vector_base<T,A> b {vb.alloc,size(),newalloc-size()}; // get new space
uninitialized_move(vb.elem,vb.elem+size(),b.elem); // move elements
swap(vb,b); // install new base
} // implicitly release old space
template<typename In, typename Out>
Out uninitialized_move(In b, In e, Out oo)
{
using T = Value_type<Out>; // assume suitably defined type function (_tour4.iteratortraits_, _meta.type.traits_)
for (; b!=e; ++b,++oo) {
new(static_cast<void*>(&*oo)) T{move(*b)}; // move construct
b->~T(); // destroy
}
return oo;
}
Перемещение от объекта просто означает, что перемещенный объект может быть пожертвовать своим мужеством, чтобы жить в другом живом объекте незадолго до того, как он [вероятно] умрет. Обратите внимание, однако, что только потому, что объект пожертвовал своей кишкой, что объект не мертв! Фактически, это может быть восстановлено другим жертвующим объектом и жить на кишках этого объекта.
Кроме того, важно понимать, что конструкция перемещения или назначение перемещения могут быть копиями! На самом деле они будут быть копиями, если перемещаемый тип относится к типу, предшествующему C ++ 11, с конструктором копирования или назначением копирования. Даже если у класса есть конструктор перемещения или назначение перемещения, он может выбрать, что он не может переместить свои кишки к новому объекту, например, из-за несоответствия распределителей.
В любом случае, перемещенный объект может по-прежнему иметь ресурсы или нуждаться в записи статистики или чего-либо еще. Чтобы избавиться от объекта, его нужно уничтожить. В зависимости от контрактов класса он может даже иметь определенное состояние после перемещения из него и может быть использован для новых целей без каких-либо дополнительных действий.
Других решений пока нет …