"IB"和"UB"究竟是什么意思?

cHa*_*Hao 104 c++ terminology definition

我已经看过多次使用术语"IB"和"UB",特别是在C++的上下文中.我试过用谷歌搜索它们,但显然这些两个字母的组合看起来很有用.:P

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

Tho*_*mas 130

IB:实现定义的行为.标准将其留给特定的编译器/平台来定义精确的行为,但需要对其进行定义.

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

UB:未定义的行为.该标准未指定调用未定义行为的程序应如何表现.也被称为"鼻子恶魔",因为理论上它可以让恶魔飞出你的鼻子.

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

  • @OregonGhost - 标准没有规定恶魔应该拥有多少角. (33认同)
  • 因为在C++中使用了未定义的行为,我还在等待恶魔飞出某人的鼻子.我想当第一个编译器完全符合新的C++标准时会发生这种情况. (11认同)
  • @Michael Burr:我更喜欢"着火".这显然是灾难性的,它至少有一种模糊的合理性(计算机硬件有时会着火,不可否认,出于硬件原因而不是软件故障,如果您正在阅读此线程的任何系统). (5认同)
  • @OregonGhost:我猜你是对的.我已经看到它发生在独角兽几次,但从来没有恶魔. (4认同)

jal*_*alf 17

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

C++标准对各种结构的效果非常具体,特别是你应该始终注意这些类别的问题:

  • 未定义的行为意味着绝对没有保证.代码可以工作,或者它可以放火烧你的硬盘或让恶魔飞出你的鼻子.就C++语言而言,绝对可能发生任何事情.实际上,这通常意味着您有一个不可恢复的错误.如果发生这种情况,你真的不能相信任何有关应用程序(因为这个不确定的行为后果之一可能是刚被弄乱你的应用程序的其它部分使用的内存).它不需要保持一致,因此两次运行程序可能会产生不同的结果.它可能取决于月亮的阶段,你穿着的衬衫的颜色,或者其他任何东西.

  • 未指定的行为意味着程序必须做一些理智和一致的事情,但不需要记录这一点.

  • 实现定义的行为类似于未指定的行为,但也必须由编译器编写者记录.一个例子是a的结果reinterpret_cast.通常,它只是更改指针的类型而不修改地址,但映射实际上是实现定义的,因此编译器可以映射到完全不同的地址,只要它记录了这个选择.另一个例子是int的大小.C++标准不关心它是2,4或8字节,但它必须由编译器记录

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

您通常还必须依赖某些实现定义的行为.这可能是不可避免的,但您仍应注意它,并注意您依赖于可能在不同编译器之间发生变化的事物.

另一方面,应始终避免未定义的行为.一般来说,您应该假设它会以某种方式爆炸您的程序.

  • @Jerry:不,UB应该避免*如果完全未定义*.如果平台/实现/运行时/编译器提供进一步的保证,那么您可以依赖行为并失去可移植性.但是它不再是未定义的......但大多数情况下,你没有这样的保证,未定义只是未定义,应该不惜一切代价避免. (3认同)

Mic*_*urr 8

  • IB:是实现定义的行为 - 编译器必须记录它的作用.>>对负值执行操作就是一个例子.

  • UB:未定义的行为 - 编译器可以做任何事情,包括简单地崩溃或给出不可预测的结果.取消引用空指针属于此类别,但也会出现像指针算术这样的更微妙的事物,它们超出了数组对象的范围.

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


Ker*_* SB 6

简短版本:

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

未定义的行为(UB):编程不正确(即错误!)

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