406 ______ Часть III. Современное программирование на C++
Определяя новый класс, сразу же объявляйте операцию присваивания, следуя следующим рекомендациям:
• Операция присваивания должна быть членом класса.
• Она возвращает ссылку на объект типа того же класса.
• Эта функция называется operator^.
• Она принимает постоянную ссылку на объект типа того же класса. Использование ключевого слова const позволяет функции работать как с постоянными объектами, так и с переменными.
Проверка на присваивание самому себе. В операции присваивания любого класса надо учитывать один важный момент. Всегда надо проверять: не происходит ли присваивания самому себе; оно может иметь место в том случае, когда объект прямо или косвенно вызывает операцию присваивания для себя. Прямое присваивание может выглядеть следующим образом:
Х х;
х = х; // присваивание себе
Это тривиальный случай; в реальных программах эта ошибка, как правило, принимает далеко не столь очевидные обличия. Присваивание себе порождает в программе утечки памяти. Такая ситуация может возникнуть, когда два объекта сообща используют некоторый ресурс и один из них этот ресурс освобождает. При этом состояние ресурса становится неопределенным, но второй объект продолжает на него ссылаться.
Есть много путей, ведущих к возникновению этой проблемы. Для ее предотвращения следует предусмотреть в операции присваивания проверку на присваивание самому себе. Она очень проста и выглядит всегда совершенно одинаково:
Х& X::operator=(const X& rhs) {
if ( this =^ &rhs) return *this; // проверка на присваивание себе // ... остальное
return *this; // возврат ссылки на объект i
Пояснения. В предыдущем разделе был рассмотрен синтаксис проверки на присваивание самому себе. Сейчас мы попробуем в ней разобраться, благо для всех операций присваивания проверка на присваивание себе совершенно одинакова. ,
Оператор
if ( this == &rhs)
проверяет, не совпадает ли аргумент с самим объектом. Указатель this содержит адрес вызывающего объекта, &rhs читается как "адрес rhs". Таким