Содержит ли сгенерированный оператор перемещения оператор delete? C++

Если мы явно определяем оператор перемещения, то мы обязаны перед самим перемещением освободить динамическую память в классе, если таковая имеется, иначе произойдет утечка памяти:

struct Example {

    int* m_ptr;

    /*...*/

    Example& operator=(Example&& another) {
        // Если тут не освободить память, то после перемещения
        // В классе не останется указателей на эту память
        delete m_ptr;
        m_ptr = another.m_ptr;
        another.m_ptr = nullptr;
    }

}

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


Ответы (1 шт):

Автор решения: HolyBlackCat

По умолчанию он выглядит примерно так:

Example &operator=(Example &&another) noexcept
{
    m_ptr = std::move(another.m_ptr);
    return *this;
}

То есть ничего не удаляет, а просто вызывает = для каждого поля.

Для сырого указателя m_ptr = std::move(another.m_ptr); эквивалентно m_ptr = another.m_ptr;.


Совет раз - используйте copy&swap idiom. В 99% случаев он позволяет не думать, что писать в operator=:

Example &operator=(Example other) noexcept
{
    std::swap(m_ptr, other.m_ptr);
    return *this;
}

Такой оператор может работать и как копирующий (если есть копирующий конструктор), и как перемещающий (если есть перемещающий конструктор). И он выдерживает бросок исключения из конструктора.


Совет два - никогда не вызывайте сами new и delete, если только вы не пишете свой контейнер или умный указатель.

Используйте стандартные контейнеры и умные указатели.

→ Ссылка