Содержит ли сгенерированный оператор перемещения оператор 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 шт):
По умолчанию он выглядит примерно так:
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, если только вы не пишете свой контейнер или умный указатель.
Используйте стандартные контейнеры и умные указатели.