Нужно ли уничтожать перемещенные объекты? - PullRequest
10 голосов
/ 04 августа 2011

Если я перевожу конструкцию 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 на трехзначное перечисление, которое различает инициализированный, неинициализированный и перемещенный из. Я просто хочу знать, если это строго необходимо.

Ответы [ 3 ]

14 голосов
/ 04 августа 2011

Да, все еще необходимо уничтожить b. Перемещенный из объекта является действительным, сконструированным объектом. В некоторых случаях он может даже содержать ресурсы, которые по-прежнему необходимо утилизировать. В общем коде, как вы показываете, T может даже не иметь конструктора перемещения. В этом случае вы можете вызвать конструктор копирования. Так что вы определенно не можете предполагать, что ~ T () не является опцией и может быть исключен.

3 голосов
/ 04 августа 2011

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

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

2 голосов
/ 04 августа 2011

Я бы хотел ответить «Нет» на ваш вопрос, но я не уверен, что это даже правильный вопрос. Учтите следующее:

{  // start of scope
    T maybe_moved;
    if(some_condition) {
        T(std::move(maybe_moved));
    }
// end of scope
}

T::~T(), очевидно, должен вызываться только один раз для объекта maybe_moved. Если бы конструктор перемещения вызвал его, как бы вы сделали такой безобидный код работающим?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...