首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >哨兵和终结者有什么区别?

哨兵和终结者有什么区别?
EN

Stack Overflow用户
提问于 2015-10-02 04:28:58
回答 2查看 4.8K关注 0票数 21

读埃里克·尼布勒的“幅度提案”时,

我遇到了“哨兵”这个词,用来代替末端迭代器。

我很难理解哨兵对结束迭代器的好处。

有人能提供一个清楚的例子,说明sentintel给表带来了标准迭代器对无法完成的任务吗?

哨兵是对过去的迭代器的抽象。哨兵是规则类型,可以用来表示范围的结束。表示范围的哨兵和迭代器应该是EqualityComparable。哨兵表示当迭代器i与哨兵相等时的元素,而i指向该元素。”-- N4382。

我认为哨兵的作用是决定范围的结束,而不仅仅是位置?

EN

回答 2

Stack Overflow用户

发布于 2017-09-22 01:01:56

引入哨兵的主要动机是有许多迭代器操作是受支持的,但对于最终迭代器end()来说通常是不需要的。例如,几乎没有必要通过*end()取消引用,通过++end()递增它,等等(*)。

相反,end()的主要用法仅仅是将其与迭代器it进行比较,以指示it是否处于它所迭代的事物的末尾。而且,与通常的编程一样,不同的需求和不同的应用也意味着一种新的类型。

range-v3库将此观察转化为一个假设(通过一个概念实现):它为end()引入了一种新类型,只要求它是相等的--与相应的迭代器相当--但不需要通常的迭代器操作)。这种新型的end()被称为哨兵。

这里的主要优点是所获得的抽象和更好的关注点分离,在此基础上编译器可能能够执行更好的优化。在代码中,基本思想是这样(这只是为了解释,与range-v3库无关):

代码语言:javascript
复制
struct my_iterator;    //some iterator
struct my_sentinel
{
     bool is_at_end(my_iterator it) const
     {
         //here implement the logic when the iterator is at the end
     }
};

auto operator==(my_iterator it, my_sentinel s)  //also for (my_sentinel s, my_iterator it)
{
    return s.is_at_end(it); 
}

看到抽象了吗?现在,您可以在is_at_end函数中实现您想要的任何检查,例如:

  • 永不停止(获得无限范围)
  • N增量后停止(以获得一个计数范围)
  • 遇到\0时停止,即*it = '\0' (用于遍历C-字符串)
  • 在12点钟(吃午饭)的时候停下来,等等。

此外,在性能方面,可以在检查中使用编译时信息(例如,将上面的N视为编译时参数)。在这种情况下,编译器可能能够更好地优化代码。

(*)请注意,这并不表示这类行动一般是没有用的。例如,--end()在某些地方很有用,参见这个问题。然而,在没有这些的情况下实现标准库似乎是可能的--这就是range-v3库所做的。

票数 5
EN

Stack Overflow用户

发布于 2015-10-02 04:37:39

哨兵和终点迭代器是相似的,因为它们标志着范围的结束。它们的检测方式不同;要么是测试迭代器本身,要么是在迭代器上测试数据值。如果您已经在对数据执行测试,那么哨兵可以允许您的算法“免费”完成,而无需进行任何额外的测试。这既可以简化代码,也可以使代码更快。

一个非常常见的前哨是用来标记字符串结尾的零字节。没有必要为字符串的末尾保留一个单独的迭代器,它可以在处理字符串本身的字符时确定。此约定的缺点是字符串不能包含零字符。

请注意,在阅读链接中的建议之前,我写了这个答案;这是哨兵的经典定义,可能与这里提出的定义不一致。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32900557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档