我应该允许我的自定义迭代器超过结束吗?

时间:2017-07-29 17:33:47

标签: c++ iterator idiomatic

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

  • operator++()是否应始终检查我是否已经过了结束?或
  • operator*()是否应该始终检查我是不是已经过了结束,而迭代器可以(无用地)提前或移动到最后?

请解决一个非调试设置,我无法确定愚蠢的开发人员是否会尝试在结束之前推进他们的指针。

3 个答案:

答案 0 :(得分:5)

这并不重要。

要符合STL约定,您需要一个begin()方法,它返回一个迭代器到集合的开头,以及一个end()方法,它将迭代器返回到最后一个元素之后。所以推进到end()和比较相等是明确的。然而,超越end()的进展并没有明确定义。最好抛出错误,但不是必需的,特别是如果涉及其他冗余检查。如果人们没有正确使用迭代器,则不对任何错误负责。

答案 1 :(得分:0)

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

我广泛使用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));

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

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

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

要记住的另一点是,如果通过运行时检查使迭代器“安全”,则最终可能会在代码中隐藏错误。因为这样的运行时检查应该引起像异常一样的可见景象,所以不要只是默默地做什么。

答案 2 :(得分:-2)

是的,不要在任何地方进行范围检查

基于@ MalcolmMclean的回答:由于C ++标准在移动到范围的末尾时没有定义迭代器的行为,所以确保它不会这样做是客户端代码的问题 - 而不是你的。所以当你没有调试时,不要因为范围检查而牺牲性能,只要假设你没有超越结束。

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