C ++ 03和C ++ 11之间未定义行为的区别是什么?

时间:2010-12-07 17:22:41

标签: c++ c++11 undefined-behavior c++03

新标准具有与旧标准不同的未定义行为。例如,新的排序规则意味着现在定义了一些过去未定义的算术运算(原因是序列点之间的多次写入)。

那么,我们需要重新学习未定义的行为?

2 个答案:

答案 0 :(得分:14)

在我看来,新规则的描述和理解都比较复杂。例如,考虑一下:

int x = 12;
x = x++ + 1; // undefined behaviour
x = ++x + 1; // valid

我建议简单地避免对同一个表达式中的同一个变量的多个副作用,这个规则更容易理解。 AFAIK C ++ 0X改变了一些过去未定义行为的案例,现在是合法用途(例如上面两个表达式中的第二个),但请记住,合法和什么之间总会存在差异。是道德的;-) ......没有人强迫你使用这些东西。

实际上,在上述情况下,第二个表达的有效性似乎是无意中发生的另一个问题(#222)在语言中的副作用。决定是使表达式有效,因为认为将某些内容从UB更改为明确定义不会造成任何伤害。然而,我认为虽然这并没有对程序造成任何损害(当然UB是最糟糕的问题),但它实际上对语言本身造成了一些损害......改变了一个已经很复杂的规则来解释和理解一个更加模糊的人。

IMO C ++正在继续从C语言自然演变为一种语言,在这种语言中,一堆好看的好语句和逻辑语句可以做很棒的事情......还有另外一堆同样好看,同样好看且同样合乎逻辑的语句可以让你的电脑爆炸。

答案 1 :(得分:3)

C ++ 0x将许多以前未定义的案例更改为现在有条件支持的案例。语义是:

  • 如果实施不支持有条件支持的功能,则应记录该功能,并对违反该功能的程序发出诊断信息。
  • 如果实现 支持它,它应该符合标准对其做出的额外要求。例如,标准可能会说实现定义的语义有条件地支持某些东西。如果是,则实现应记录它如何支持该功能。

以前未定义的流行案例是传递类类型的参数,它具有非平凡的复制构造函数,非平凡的移动构造函数或通过省略号函数参数的非平凡的析构函数。这是现在有条件支持的,具有实现定义的语义。