Сегодня, когда я писал код 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");
Это происходит из истории использования целочисленных значений в качестве логических.
Если x
- это int
, но я использую его как логическое значение согласно if (x) ...
, то увеличение будет означать, что все его значение истинности перед операцией, оно будет иметь значение истинности истина
после него (исключение переполнения).
Однако невозможно предсказать результат -
, зная только значение истинности x
, так как это может привести к ложному
(если интегральное значение равно 1) или истина
(если интегральное значение - любое другое - в частности, это включает 0 [ ложь
] и 2 или более [ истина
]) .
Таким образом, сокращенный вариант ++
работал, а -
- нет.
++
разрешено в 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
в качестве логического.
ANSI ISO IEC 14882 2003 (c ++ 03):
5.2.6-2
Операнд постфикса - это уменьшается аналогично постфиксу ++ оператор, за исключением того, что операнд не должен иметь тип bool. [Примечание: для приращение и уменьшение префикса, см. 5.3.2. ]
И неудивительно ...
5.3.2-2
Операнд префикса - изменен путем вычитания 1. Операнд должен не относиться к типу bool. Требования на операнде префикса - и свойства его результата иначе такие же, как у префикса ++. [Примечание: Для постфиксного инкремента и декремента, см. 5.2.6. ]
Также в 5.6.2-1 и 5.3.2-1 упоминается, что ++ для bools должно быть истинным, а в Приложении D-1 сказано, что ++ для bools устарело.
По историческим причинам это было поддержано. Но учтите, что ... Использование операнда типа bool с оператором ++ не рекомендуется, см. Раздел 5.3.2 в стандарте C ++ (n3092)
5.3.2 Увеличение и уменьшение [expr.pre.incr]