In 查看 C++ 反向迭代器的另一种方式 https://devblogs.microsoft.com/oldnewthing/20211112-00/?p=105908雷蒙德·陈写道:
... C++ 语言的一个怪癖:你可以拥有一个指针
集合的“已过终点”,但不允许您拥有
集合的“开始之前的一个”指针。
我知道这可能意味着“未定义的行为”,这几乎是一个对话结束者。但我很好奇如果忽略这一规则,在现实系统中可能发生的最糟糕的情况是什么。分段错误?指针算术溢出?不必要的分页?
请记住,开头“之前”的指针(如“结束”)也不应该被引用,问题似乎只是指针trying指向它。
我能想象到的唯一可能出现问题的情况是内存位置“0”有效的系统。
但即便如此,如果是这样的话,还会有更大的问题(例如 nullptr 本身也会有问题,我猜按照惯例,环绕可能仍然有效。)
我并不是质疑实施reverse_iterator
带有一个相差一的特殊代码。
我想到了这个问题,因为如果您有“跨步”迭代器的通用实现,则需要负跨步的特殊逻辑,并且会产生成本(在代码中和运行时)。
任意步幅(包括负步幅)可能会自然地出现在多维数组中。
我有一个多维数组库,原则上我总是允许负步幅,但现在我意识到,如果我允许它们,它们应该有一个特殊的代码(与正向情况不同),并且我不想暴露未定义的行为。
但我很好奇现实中可能发生的最糟糕的情况是什么
系统如果忽视这一规则。分段错误?的溢出
指针算术?不必要的分页?
浪费空间。
为了能够形成“前一”地址,您需要有可用空间。例如,如果您有一个 1k 结构,则它必须从内存开头至少 1k 开始。在内存有限的小型设备或具有分段内存的 x86 上,这可能会很棘手。
要形成“过去”的指针/迭代器,您只需要在末尾之外一个字节。由于无论如何都无法取消引用它,因此不需要为整个对象提供空间,只需可以形成地址即可。
来自评论:
在定义规则时,我们拥有带有专用地址寄存器的真实 CPU,可以根据寄存器加载时的段大小验证地址。这确保了 -1 地址会陷入困境......
https://en.wikipedia.org/wiki/Motorola_68000#Architecture https://en.wikipedia.org/wiki/Motorola_68000#Architecture
这排除了“前一个”环绕到段末尾的情况。因为如果段很小,最终的末端可能不存在。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)