Ребяты! Тут мы кое с кем (не будем говорить с кем, хотя это был Альф) посоветовались и подумали, что может быть кому-то из программистов будет интересна тема о тестировании программ и использующихся для этого методах и инструментах? Ну возможно и какой-никакой профессиональный тестировщик забежит.
Пожалуйста, кого занимает подобная тематика, скажите об этом.
В процессе разбора накопившихся за годы тем, появилась идея создать специальный раздел форума для вопросов, которые могут стать основой для статей.
operator= Рассмотрим подробно.
Часть 2. Проверка на присваивание самому себе. А зачем?
Итак, продолжим подробное рассмотрение функции operator=. В этот раз разберемся, зачем же нужна проверка на присваивание самому себе.
Когда возникает ситуация с присваиванием самому себе? Ситуация "по определению проблемы" выглядит так:
class Something { … //содержимое класса … };
Something S;
S=S;
Трудно придумать, зачем такая конструкция может понадобиться. Тем не менее, она вполне допустима правилами С++. Более приемлемой выглядит такая запись:
Something &W = S;
S=W;
Несколько менее очевидно, но то же самое. Здесь W – это просто другое обозначение для S. Это ссылка, инициализированная S. То есть объект S просто имеет теперь два разных "имени". Такое совмещение имен может возникнуть в самых разных случаях, поэтому такую возможность просто необходимо учитывать.
Теперь давайте посмотрим, к чему приводит отсутствие проверки на присваивание самому себе.
В статье "Классы. Копирование и присваивание. Часть 4" уже был рассмотрен вопрос, как реализовать копирование через присваивание для объектов производных классов. Там говорилось о том, что оператор присваивания производного класса должен вызывать оператор присваивания своего базового класса. А если базовый класс для него и сам является производным от другого? И такая иерархия очень длинная? В таком случае, если в самом начале оператора присваивания обнаружится ситуация с присваиванием самому себе,
можно (и нужно) просто сразу выйти из него, избегая целого ряда ненужных функциональных вызовов. При этом как минимум может повыситься эффективность.
Но не это главное. Вспомните – оператор присваивания перед тем как выделить новый блок памяти, должен для начала освободить ресурсы, выделенные объекту ранее (то есть избавиться от старых значений). При присваивании самому себе освобождение памяти может просто "угробить" старые ресурсы, которые могут понадобиться для создания новых.