Правила программирования на С и С++. Главы 7-8 - Присваивание самому себе должно работать
ОГЛАВЛЕНИЕ
124. Операция operator=( ) должна возвращать ссылку на константу.
125. Присваивание самому себе должно работать.
Определение operator=( ) должно всегда иметь следующую форму:
class class_name{
const class_name ?operator=( const class_name ?r );};const class_name ?class_name::operator=( const class_name ?r )
{
if( this != ?r ){
// здесь скопировать}return *this;
}Аргумент, представляющий операнд источника данных, является ссылкой, чтобы избежать накладных расходов вызова по значению; это ссылка на константу, потому что аргумент не предназначен для модификации.
Эта функция возвращает ссылку, потому что она может это сделать. То есть вы могли бы удалить ? из объявления возвращаемой величины, и все бы работало прекрасно, но вы бы получили ненужный вызов конструктора копии, вынужденный возвратом по значению. Так как у нас уже есть объект, инициализированный по типу правой части (*this), то мы просто можем его вернуть. Даже если возврат объекта вместо ссылки в действительности является ошибкой для функции operator=(), компилятор просто выполнит то, что вы ему приказали. Здесь не будет сообщения об ошибке; и на самом деле все будет работать. Код просто будет выполняться более медленно, чем нужно.
Наконец, operator=() должен возвращать ссылку на константу просто потому, что не хотите, чтобы кто-нибудь имел возможность модифицировать возвращенный объект после того, как произошло присваивание. Следующее будет недопустимым в случае возврата ссылки на константу:
(x =y) = z;Причина состоит в том, что (x=y) расценивается как возвращаемое значение функции operator=(), т.е. константная ссылка. Получателем сообщения =z является объект, только что возвращенный от x=y. Тем не менее, вы не можете послать сообщение operator=() константному объекту, потому что его объявление не имеет в конце const: // НЕ ДЕЛАЙТЕ ЭТОГО// В ФУНКЦИИ С ИСПОЛЬЗОВАНИЕМ
// operator=().
// |
// V
const class_name ?operator=( const class_name ?r ) const;Компилятор должен выдать вам ошибку типа "не могу преобразовать ссылку на переменную в ссылку на константу", если вы попробуете (x=y)=z.Другим спорным моментом в предыдущем коде является сравнение:
if( this != ?r )в функции operator=(). Выражение: class_name x;// ...
x = x;
должно всегда срабатывать, и сравнение this с адресом входного правого аргумента является простым способом в этом убедиться. Имейте в виду, что многие алгоритмы полагают самоприсваивание безвредным, поэтому не делайте его особым случаем. Также имейте в виду, что самоприсваивание могло бы быть затушевано при помощи указателя как в: class_name array[10];class_name *p = array;
// ...
*p = array[0];