我应该让我的自定义迭代器结束吗?

Should I allow my custom iterator to go past the end?

我正在为基于索引的 class 实现迭代器。有一个最大有效值;我的问题是当客户端代码将迭代器推进到我的 end() 值之外时该怎么办:

请解决一个非调试设置,在该设置中我无法确定愚蠢的开发人员不会尝试将他们的指针推进到末尾。

没关系。

为了符合 STL 约定,您需要一个 begin() 方法,它 returns 一个指向集合开头的迭代器,以及一个 end() 方法,它 returns 一个指向过去的迭代器最后一个元素。因此,前进到 end() 并比较是否相等是明确定义的。然而,超越 end() 的进展并没有明确定义。最好抛出一个错误,但不是必须的,尤其是在涉及其他冗余检查的情况下。如果人们没有正确使用迭代器,您不对任何错误负责。

是的,不要为范围检查而烦恼任何地方

基于@MalcolmMclean 的回答:由于 C++ 标准没有定义迭代器在超出范围末尾时的行为,因此确保它不会那样做是客户端代码的问题 - 而不是您的问题。所以当你不调试的时候,不要为了范围检查而牺牲性能,假设你没有超过终点。

当您正在 编译调试时,正如@Phil1970 所建议的那样,使用异常抛出或使用断言进行范围检查可能是个好主意。

我所做的是在编译调试版本时添加严格的检查代码,并在代码的发布版本中删除这些检查。

我广泛使用 assert(或类似的)。它执行 运行 时间检查 除非 您使用定义的宏 NDBUG 进行编译,在这种情况下完全消除检查。

STL 哲学本身应该提供一种安全措施,因为迭代器限制通常来自安全的地方。

当您运行一个算法时,您通常会从这样的容器中获取边界:

std::vector<int> v {1, 2, 3, 4};

do_some_stuff(std::begin(v), std::end(v));

否则你可能会得到你的迭代器作为算法的结果:

auto found_iter = std::find(std::begin(v), std::end(v));

这使得使用迭代器非常安全。当您开始使用迭代器 athematic 时,它会变得有点危险:

auto dangerous_iter = std::begin(v) + 5; // not encouraged 

但是应该在调试阶段使用 assert 和类似方法捕获错误。

要记住的另一点是,如果您通过 运行 时间检查来创建迭代器 "safe",您可能会在代码中隐藏错误。因此,这样的 运行 时间检查应该会像异常一样引起可见的现象,不要只是静静地什么都不做。