Стандарты программирования на С++




Обсуждение


Главная причина отказа от перегрузки операторов operator&&, operator|| и operator, (запятая) состоит в том, что вы не имеете возможности реализовать полную семантику встроенных операторов в этих трех случаях, а программисты обычно ожидают ее выполнения. В частности, встроенные версии выполняют вычисление слева направо, а для операторов && и || используются сокращенные вычисления.

Встроенные версии && и || сначала вычисляют левую часть выражения, и если она полностью определяет результат (falseдля &&, true для ||), то вычислять правое выражение незачем — и оно гарантированно не будет вычисляться. Таким образом мы используем эту возможность, позволяя корректности правого выражения зависеть от успешного вычисления левого:

Employee* e = TryToGetEmployee(); if( e && e->Manager() ) // ...

Корректность этого кода обусловлена тем, что e->Manager() не будет вычисляться, если e имеет нулевое значение. Это совершенно обычно и корректно — до тех пор, пока не используется перегруженный оператор operator&&, поскольку в таком случае выражение, включающее &&, будет следовать правилам функции:

вызовы функций всегда вычисляют все аргументы до выполнения кода функции;

порядок вычисления аргументов функций не определен (см. также рекомендацию 31).

Давайте рассмотрим модернизированную версию приведенного ранее фрагмента, которая использует интеллектуальные указатели:

some_smart_ptr<Employee> e = TryToGetEmployee(); if( e && e->Manager() ) // ...

Пусть в этом коде используется перегруженный оператор operator&& (предоставленный автором some_smart_ptrили Employee). Тогда мы получаем код, который для читателя выглядит совершенно корректно, но потенциально может вызвать e->Manager() при нулевом значении e.

Некоторый иной код может не привести к аварийному завершению программы, но стать некорректным по другой причине — из-за зависимости от порядка вычислений двух выражений. Результат может оказаться плачевным. Например:

if( DisplayPrompt() && GetLine() ) // ...




Содержание  Назад  Вперед