【发布时间】:2026-01-19 00:10:02
【问题描述】:
在Another way of looking at C++ reverse iteratorsRaymond Chen 写道:
... C++ 语言的一个怪癖:你可以有一个指针 一个集合的“一个过去的结束”,但你不能有一个 集合的“开头前一个”指针。
我知道这可能意味着“未定义的行为”,这几乎是一个对话终结者。但是我很好奇如果忽略这条规则,在现实系统中可能发生的最坏情况是什么。分段错误?指针算术溢出?不必要的分页?
请记住,指针“之前”(如“end”)也不应该被引用,问题似乎是指针只是试图指向它。
我能想象的唯一可能出现问题的情况是内存位置“0”有效的系统。 但即便如此,如果是这样的话,还有更大的问题,(例如 nullptr 本身也会有问题,我猜想按照惯例,环绕可能仍然有效。)
我不是在质疑reverse_iterator 的实现,它带有一个非一的特殊代码。
我想到了这个问题,因为如果你有一个“跨步”迭代器的通用实现,那么负跨步需要一个特殊的逻辑,并且有成本(在代码和运行时)。
任意步幅,包括负步幅,自然会出现在多维数组中。 我有一个多维数组库,原则上我总是允许负步幅,但现在我意识到,如果我完全允许它们并且我不想暴露未定义的行为,它们应该有一个特殊的代码(不同于正例) .
【问题讨论】:
-
“可能发生的最坏情况” 优化器感到困惑并做着奇怪的事情。或者遇到奇怪的崩溃,不得不怀疑它是否是由这个 UB 引起的。
-
The LLVM Project Blog - What Every C Programmer Should Know About Undefined Behavior #1/3 即编译器可以对你做什么。这不仅仅是段错误;当编译器确定一段代码包含 UB 时,它可以删除/更改/“变得奇怪”。
-
还有Old New Thing - Undefined behavior can result in time travel (among other things, but time travel is the funkiest) 即担心运行时错误但也担心编译器会将您的代码更改为您不希望的内容。
-
阿丽亚娜号可能会爆炸,或者火星任务失败,人员伤亡很多。这意味着,软件不再被认为是安全的。
-
除了对未定义行为的一般关注之外,我认为在这种情况下在现代机器上不会发生任何不好的事情(使用平面内存模型和 2 的补码算法)。原因是编译器(通常)不能证明指针指向分配的开始。它可能指向中间。在这种情况下,
ptr[-1]是有效的。因此,编译器失控并没有太大意义。
标签: c++ reverse-iterator