【问题标题】:Why does the C++ standard not deprecate the increment/decrement operators? [closed]为什么 C++ 标准不弃用递增/递减运算符? [关闭]
【发布时间】:2013-09-19 14:26:16
【问题描述】:

我认为下面的代码是邪恶的,但它可以在没有任何警告的情况下编译。

int f(int n)
{
    return n + 1;
}

int n = 0;
n = f(n++) + f(++n);

我只是想知道为什么神圣标准不弃用此类运算符?

我想可能有两个原因:

一个可能是为了向后兼容;

另一个可能是在某些情况下这些运算符非常有用。

如果后者是真的,你能给我举几个例子吗?谢谢。

【问题讨论】:

  • 好吧,如果我没记错的话,上面的表达式被定义为未定义(双关语)行为。是的,运算符本身非常有用、紧凑且易读。
  • “我只是想知道为什么神圣标准不弃用这些运算符?”它不会弃用它们,因为没有人编写这样的代码。
  • 仅仅因为某些东西可能最终被错误地使用并不意味着它必须从标准中删除。有很多 evil 东西在没有任何警告的情况下编译得很好。
  • 您使用哪个编译器可以毫无怨言地编译代码?使用 GCC 4.8.1(C 和 C++ 编译器),我得到:x3.cpp:11:14: error: lvalue required as increment operand 突出显示声明 n = f(++n++) + f(++n++); — 所有编译器都应该给出该错误,AFAIK。
  • @JonathanLeffler 我们有一个经典的“不是真正的代码”问题:OP 将他们的帖子从f(++n++) + f(++n++) 编辑为f(n++) + f(++n),这是一个相当可笑的不同问题。它们都使用 ascii 字符以及前置和后置运算符,因此它们并不完全不同。

标签: c++ c coding-style standards unary-operator


【解决方案1】:

它不仅仅是邪恶,它是 Undefined Behaviour™。这就是为什么所有理智的人都禁止这种用途。

向后兼容性肯定是问题的一半 - 到处都在使用递增和递减。它们对于迭代器和其他东西也很有用。

底线是,C++ 从来没有阻止过你在自己的脚下开枪。这只是一个例子。 C++ 不会仅仅因为它们可能是坏的而禁止可能是好的东西。不滥用它们是你的问题。

【讨论】:

  • -1 这是不是未定义的行为。每个函数调用之前都有一个序列点。这是未指明的行为,是完全不同的野兽。
  • 啊,没关系,我只是注意到自从您发布此帖子后,OP 已经编辑了他们的帖子。已删除反对票。
【解决方案2】:

从 C 和/或 C++ 中删除这些 ++ 和 -- 运算符肯定会破坏很多代码 - 事实上我怀疑,如果你删除这两个运算符,几乎每个现有的源文件都将停止编译.

它们在正确使用时非常有用——只要你不在同一个变量的两边都使用它,你会没事的。

此代码无法编译,但添加括号使其 (++n)++ 可以正确编译 - 但 g++ 给出警告“对‘n’的操作可能未定义”。

如果我们去掉++ 和-- 运算符,你希望如何编写一个通用的for-lopp:

for(int i = 0; i < 100; i++)

像这样:

for(int i = 0; i < 100; i = i + 1)

或

for(int i = 0; i < 100; i += 1)

禁止在 C 和 C++ 中可能被滥用的所有内容几乎会使该语言变得毫无用处 - 并且肯定会使该语言完全无用或至少阻止许多有效用途。这就像禁止使用刀具,因为人们可以使用它们(并且确实使用它们)做坏事。但如果你想切面包、肉或蔬菜,他们确实会为此制作非常方便的工具。

【讨论】:

  • @Gangadhar 我不知道,肯定的对i 来说似乎很有价值。
  • @Eric:感谢您的澄清。但是,我很确定 OP 打算在相对较短的时间内停止使用该功能 [这是我的解释],这意味着,在“宽限期”之后,任何未修改的代码都将停止工作。我将改写第一句话。
【解决方案3】:

我只是想知道为什么神圣标准不弃用此类运算符?

因为这是完全有效的代码,但它调用了未指定的行为,因为未指定 C 表达式中操作数的求值顺序。代码中唯一的问题是由程序员创建的,他编写的代码依赖于未指定的行为。对程序员进行语言培训不是 C 标准的任务。

(这是不是未定义的行为。参见 C11 6.5.2.2。在函数调用和实际调用中函数指示符和实际参数的评估之间存在一个序列点。如果不是对于每个函数参数评估之后的序列点,这将是未定义的行为,因为您不能在没有序列点的操作中两次修改同一个变量。)

一个可能是为了向后兼容;

没有。 C 一直有未指定的操作数求值顺序。此代码从标准前的 K&R 代码一直到 C11 的工作方式都是一样的。

另一个可能是在某些情况下这些运算符非常有用。

不,您发布的代码在任何情况下都没有用。它被混淆了,可以用更好的方式编写,以更安全、更易读的方式实现相同的功能和相同的机器代码。例如:

n++;
n = f(n) + f(n);
n++;

【讨论】:

  • 6.5.2.2 告诉我们,对f 的第一次调用(按源文本顺序)在评估n++ 之后评估,第二次调用在评估++n 之后评估。它并没有告诉我们在调用 f 之前,实现可能不会同时评估 n++ 和 ++n。
猜你喜欢
  • 2023-01-05
  • 2011-04-09
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 2013-11-16
  • 2011-02-16
相关资源
最近更新 更多