“ IB”和“ UB”到底是什么意思?

我已经多次看到术语“ IB”和“ UB”被使用,特别是在 C + + 的上下文中。我试过谷歌搜索,但显然这两个字母的组合很有用。校对: P

所以,我问你... 当他们被说成是坏事的时候,他们是什么意思?

25508 次浏览

IB: 实现定义的行为。这个标准让特定的编译器/平台来定义精确的行为,但是要求它被定义。

使用实现定义的行为可能很有用,但是会使代码的可移植性降低。

未定义行为。该标准没有指定调用未定义行为的程序应该如何运行。也被称为“鼻腔恶魔”,因为理论上它可以使恶魔飞出你的鼻子。

使用未定义的行为几乎总是一个坏主意。即使有时它看起来可以工作,任何对环境、编译器或平台的更改都会随机地破坏您的代码。

  • 是实现定义的行为-编译器必须记录它所做的事情。对负值执行 >>操作就是一个例子。

  • 未定义行为-编译器可以做任何事情,包括简单地崩溃或给出不可预测的结果。解除空指针的引用属于这个类别,但是也有一些更微妙的事情,比如指针算法超出了数组对象的界限。

另一个相关的术语是“未指明的行为”。这是一种介于实现定义的和未定义的行为之间。对于未指定的行为,编译器必须根据标准执行某些操作,但标准给出的确切选择由编译器决定,不需要定义(甚至不需要一致)。像子表达式的求值顺序就属于这一类。编译器可以按照它喜欢的顺序执行这些操作,并且可以在不同的构建中执行不同的操作,甚至在同一个构建的不同运行中执行不同的操作(不太可能,但是允许)。

实现定义的行为和未定义行为

The C++ standard is very specific about the effects of various constructs, and in particular you should always be aware of these categories of trouble:

  • 未定义行为意味着绝对不会给出任何保证。该代码可以工作,或者它可以放火烧你的硬盘或 让恶魔从你鼻子里飞出来。就 C + + 语言而言,任何事情都有可能发生。实际上,这通常意味着您有一个不可恢复的错误。如果发生这种情况,你就不能真正相信你的应用程序中的 什么都行(因为这种未定义行为的一个影响可能就是搞乱了应用程序其余部分使用的内存)。它不需要是一致的,因此运行两次程序可能会得到不同的结果。这可能取决于月相,你所穿的衬衫的颜色,或者其他任何东西。

  • 未指定的行为意味着程序必须做一些正常和一致的事情,但是 文件不需要这样做。

  • 实现定义的行为类似于未指定的行为,但也必须由编译器编写器记录。这方面的一个例子是 reinterpret_cast的结果。usually,它只是改变指针的类型,而没有修改地址,但是映射实际上是实现定义的,所以编译器 可以映射到一个完全不同的地址,只要它记录了这个选择。另一个例子是 int 的大小。C + + 标准并不关心它是2、4还是8字节,但是编译器会记录 必须的

但所有这些问题的共同点是,最好避免这些问题。如果可能的话,坚持使用 C + + 标准本身100% 指定的行为。这样,你就可以保证移植性。

You often have to rely on some implementation-defined behavior as well. It may be unavoidable, but you should still pay attention to it, and be aware that you're relying on something that may change between different compilers.

另一方面,应避免使用未定义行为。一般来说,您应该假设它会使您的程序以这种或那种方式爆炸。

简而言之:

实现定义的行为(IB) : 正确编程但不确定 *

Undefined behaviour (UB): Incorrectly programmed (i.e. a 臭虫!)

*)就语文水平而言,“不确定”当然是在任何固定的平台上确定的。