оператор bool ++ и - - PullRequest
       17

оператор bool ++ и -

100 голосов
/ 10 августа 2010

Сегодня при написании кода на Visual C ++ я натолкнулся на то, что меня удивило.Кажется, C ++ поддерживает ++ (приращение) для bool, но не - (приращение).Это просто случайное решение, или за этим есть какая-то причина?

Это компилируется:

static HMODULE hMod = NULL;
static bool once = false;
if (!once++)
    hMod = LoadLibrary("xxx");

Это не так:

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");

Ответы [ 4 ]

88 голосов
/ 10 августа 2010

Из истории использования целочисленных значений в качестве логических значений.

Если x является int, но я использую его как логическое значение согласно if(x)..., то приращение будет означать, что независимо от значения истинности перед операцией, оно будет иметь значение истинности true после него (за исключением переполнения).

Однако невозможно предсказать результат --, учитывая знание только истинного значения x, так как это может привести к false (если целое значение равно 1) или true (если Интегральное значение - это что-нибудь еще, в частности, это 0 [false] и 2 или более [true]).

Так как короткая рука ++ сработала, а -- - нет.

++ разрешено для bools для совместимости с этим, но его использование не рекомендуется в стандарте.


Предполагается, что я только использую x в качестве логического значения, что означает, что переполнение не может произойти, пока я не выполню ++ достаточно часто, чтобы вызвать переполнение самостоятельно. Даже если использовать тип char и CHAR_BITS что-то низкое, например, 5, это 32 раза, прежде чем это больше не работает (этого все еще достаточно для того, чтобы это было плохой практикой, я не защищаю практику, просто объясняю, почему это работает) для 32-битного int нам, конечно, пришлось бы использовать ++ 2 ^ 32 раза, прежде чем это станет проблемой. С --, хотя это приведет к false, только если я начал со значения 1 для true или начал с 0 и использовал ++ точно один раз до этого.

Это отличается, если мы начнем со значения, которое всего на несколько ниже 0. Действительно, в таком случае мы можем захотеть, чтобы ++ в конечном итоге приводил к значению false, например, как:

int x = -5;
while(++x)
  doSomething(x);

Однако в этом примере x рассматривается как int везде, кроме условного, поэтому он эквивалентен:

int x = -5;
while(++x != 0)
  doSomething(x);

Что отличается от использования x в качестве логического значения.

30 голосов
/ 10 августа 2010

ANSI ISO IEC 14882 2003 (c ++ 03):

5.2.6-2

Операнд постфикса - уменьшается аналогичнок оператору postfix ++, за исключением того, что операнд не должен иметь тип bool.[Примечание: для увеличения и уменьшения префикса, см. 5.3.2.]

И неудивительно, что ...

5.3.2-2

Операнд префикса - модифицируется вычитанием 1. Операнд долженне быть типа бул.Требования к операнду префикса - и свойства его результата в остальном такие же, как и у префикса ++.[Примечание: для увеличения и уменьшения постфикса, см. 5.2.6.]

Также в 5.6.2-1 и 5.3.2-1 упоминается, что ++ для bools должен быть верным, а в Приложении D-1 говорится, что ++ для bools устарела.

9 голосов
/ 10 августа 2010

По историческим причинам это было поддержано. Но обратите внимание, что ... Использование операнда типа bool с оператором ++ не рекомендуется, см. Раздел 5.3.2 в стандарте C ++ (n3092)

5.3.2 Увеличение и уменьшение [expr.pre.incr]

  • Операнд префикса ++ изменен добавив 1, или установите значение true, если это bool (это использование устарело). операнд должен быть изменяемым значением l. Тип операнда должен быть арифметический тип или указатель на полностью определенный тип объекта. результат - обновленный операнд; это lvalue, и это битовое поле, если операнд является битовым полем. Если х не типа bool, выражение ++ x эквивалентно x + = 1 [Примечание: см. обсуждение дополнения (5.7) и операторы присваивания (5.17) для информация о конверсиях. —Конечная записка ]
  • Операнд префикса - изменен вычитая 1. Операнд должен не быть типа бул. Требования на операнде префикса - и Свойства его результата в остальном такой же как у префикса ++.
2 голосов
/ 23 марта 2016
  • При старых стандартах (C ++ 98) это не ошибка.
  • С увеличением новых стандартов логическое значение устарело.(C ++ 11)
  • Вы можете использовать инкремент логического значения до C ++ 17.
...