Перемещаются - из объектов, требуемых для уничтожения?
Если я перемещаю-конструкцию a
из b
, все же необходимо уничтожить b
, или я могу уйти без этого?
Этот вопрос перешел мне в голову при реализации шаблона optional<T>
. Выдержки:
~optional()
{
if (initialized)
{
reinterpret_cast<T*>(data)->~T();
}
}
optional(optional&& o) : initialized(o.initialized)
{
if (initialized)
{
new(data) T(std::move(*o)); // move from o.data
o.initialized = false; // o.data won't be destructed anymore!
}
}
Конечно, я мог бы просто заменить bool initialized
трехзначным перечислением, которое различает инициализированный, неинициализированный и перемещенный. Я просто хочу знать, нужно ли это строго.
Ответы
Ответ 1
Да, по-прежнему необходимо уничтожить b
. Перемещенный из объекта - действительный, построенный объект. В некоторых случаях он может даже содержать ресурсы, которые по-прежнему необходимо утилизировать. В общем коде, который вы показываете, T
может даже не иметь конструктор перемещения. В этом случае вы можете ссылаться на конструктор копирования. Таким образом, вы можете определенно не предполагать, что ~ T() является no-op и может быть отменено.
Ответ 2
Да, вам все равно придется их уничтожить. Один из проектов, который может показать этот недостаток, - это, например, шаблоны, основанные на наблюдателях, где один объект хранит списки указателей на другой. Не запускать деструктор не удаляет указатель, и код будет сбой при попытке доступа к объекту, который больше не существует.
В вашем примере проще всего не инициализировать false в перемещенном объекте. Значение по-прежнему определено в правильном состоянии после перемещения из него, а деструктор значения r, о котором вы говорите, очистит его без дальнейшего вмешательства.
Ответ 3
Я бы хотел ответить "Нет" на ваш вопрос, но я не уверен, что это даже правильный вопрос. Рассмотрим следующее:
{ // start of scope
T maybe_moved;
if(some_condition) {
T(std::move(maybe_moved));
}
// end of scope
}
T::~T()
, очевидно, должен быть вызван только один раз для объекта maybe_moved
. Если конструктор перемещения вызовет его, как бы вы сделали такой безобидный код, работающий?