106

今天在编写一些 Visual C++ 代码时,我遇到了一些令我惊讶的事情。似乎 C++ 支持布尔的 ++(增量),但不支持 -- (减量)。这只是一个随机决定,还是背后有某种原因?

这编译:

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

4 回答 4

94

它来自使用整数值作为布尔值的历史。

Ifx是一个int,但我将它用作布尔值,if(x)...然后递增将意味着无论它在操作之前的真值如何,它都将true在它之后具有一个真值(除非溢出)。

但是,不可能--仅预测给定知识的结果 的真值x,因为它可能导致false(如果积分值为 1)或true(如果积分值为其他任何值 - 特别是这包括 0 [ false] 和 2 或更多 [ true])。

所以作为一个短手++工作,并--没有。

++为了与此兼容,允许在 bool 上使用,但在标准中已弃用它,并在 C++17 中将其删除。


这假设我用作x布尔值,这意味着溢出不会发生,直到我++经常完成足以导致它自己的溢出。即使使用 char 作为使用的类型并且CHAR_BITS像 5 这样的低值,在这不再起作用之前是 32 次(这仍然足以证明它是一种不好的做法,我不是为这种做法辩护,只是解释它为什么起作用)对于 32 位int,我们当然必须使用++2^32 次才能成为问题。--虽然它只会导致如果我以false1 的值true开始,或者以 0 开始并且++之前精确使用过一次。

如果我们从一个略低于 0 的值开始,情况就不同了。确实,在这种情况下,我们可能希望最终++得到该false值,例如:

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

但是,此示例将除条件之外的任何地方都x视为一个int,因此它等效于:

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

这与仅用x作布尔值不同。

于 2010-08-10T15:26:20.943 回答
29

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

5.2.6-2

后缀 -- 的操作数与后缀 ++ 运算符类似地递减,不同之处在于操作数的类型不应为 bool。[注:前缀递增和递减见 5.3.2。]

而且不出所料...

5.3.2-2

prefix-- 的操作数通过减 1 进行修改。操作数不得为 bool 类型。对prefix--操作数的要求及其结果的性质与prefix ++的要求相同。[注:后缀递增和递减见 5.2.6。]

此外,5.6.2-1 和 5.3.2-1 提到布尔值的 ++ 应该是正确的,附件 D-1 说布尔值的 ++ 已弃用。

于 2010-08-10T15:22:26.143 回答
9

由于历史原因,这得到了支持。但请注意...... 不推荐使用带有 ++ 运算符的 bool 类型的操作数,请参阅 C++ 标准 (n3092) 中的第 5.3.2 节

5.3.2 递增和递减[expr.pre.incr]

  • 前缀 ++ 的操作数通过加 1 来修改,或者如果它是 bool 则设置为 true(不推荐使用此用法)。操作数应为可修改的左值。操作数的类型应为算术类型或指向完全定义的对象类型的指针。结果是更新的操作数;它是一个左值,如果操作数是一个位域,它就是一个位域。如果 x 不是 bool 类型,则表达式 ++x 等价于 x+=1 [ 注意:有关转换的信息,请参见加法 (5.7) 和赋值运算符 (5.17) 的讨论。——尾注]
  • prefix-- 的操作数通过减 1 进行修改。操作数不得为 bool 类型。对prefix--操作数的要求及其结果的性质与prefix ++的要求相同。
于 2010-08-10T15:28:33.093 回答
3
  • 使用旧标准 (C++98) 这不是错误。
  • 随着新标准的增加,不推荐使用布尔值。(C++11)
  • 在 C++17 之前,您可以对布尔值使用增量。
于 2016-03-23T06:18:38.063 回答