Страницы

Поиск по вопросам

понедельник, 30 декабря 2019 г.

Почему operator++ должен возвращать const T?

#cpp #операторы #типы


const T T::operator++(int)
{
    T tmp = *this;
    ++(*this);
    return tmp;
}


Рассмотрим такой вариант реализации постфиксного оператора инкрементирования. Почему
требуется возвращать именно const T, а не T? Такой вариант реализуется для типа int,
а нужно ли мне реализовывать этот оператор для своего пользовательского типа аналогично?

Я придерживался негласного правила, что при разработке классов (типов) в случае если
непонятно (или еще не сформулировано) требуемое поведение то следует организовать поведение,
какое предоставляет int. int возвращает const int. А нужно ли и мне так?
    


Ответы

Ответ 1



Нет необходимости делать возвращаемый тип константым, чтобы избежать двойного инкремента ++++. Достаточно объявить оператор инкремента только для lvalue объектов (добавить & в сигнатуру): struct T { T operator++(int) & { return *this; } }; int main() { T t; t++; // ok t++++; // ошибка }

Ответ 2



Постфиксный оператор инкрементирования (оператор декрементирования аналогнично) возвращает const T, чтобы предотвратить потенциально некорректное использование некоторых конструкций, т.к. двойное постфиксное инк-/дек- рементирование вида i++++. В силу особенностей реализации этого оператора возвращается прошлое значение объекта, поэтому второй вызов оператора operator++(int) изменит значение возвращенной первым оператором копии исходного объекта, а не результата с учетом первого инкрементирования. Как правило, клиентский код обычно не требует (вообще говоря, не должен) поддержки таких конструкций, как двойное применение постфиксного оператора и одновременное изменение значения, возвращаемого постфиксным оператором, в одной инструкции, поэтому запрет подобной операции через const T вполне оправдан. Ошибок избегать это помогает точно.

Ответ 3



const T в результате функции запрещает неконстантные операции, в частности перемещение (move-семантика). struct X { X(X&&); const X operator++(int); int& operator*(); }; X a; X b = a++; // тут будет копирование, а не перемещение *a++ = 1; // не скомпилируется

Комментариев нет:

Отправить комментарий