【问题标题】:Advance iterator for the std::vector std::advance VS operator +?std::vector std::advance VS 运算符的高级迭代器 +?
【发布时间】:2010-12-12 16:34:17
【问题描述】:

我发现自己写了很多:

int location =2;
vector<int> vec;
vector<int>::iterator it=vec.begin();

/..../
std::advance(it, location);

而不是

 it= it + 5;

首选/推荐方式是什么?

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    添加仅适用于随机访问迭代器。 std::advance 将适用于各种迭代器。只要您只处理向量中的迭代器,它就没有真正的区别,但std::advance 使您的代码更通用(例如,您可以用list 替换vector,这部分仍然可以工作) .

    对于那些关心的人,标准将advancedistance 描述如下(§24.3.4/1):

    由于只有随机访问迭代器提供 + 和 - 运算符,因此库提供了两个函数模板 advancedistance。这些函数模板将+- 用于随机访问迭代器(因此它们的时间是常数);对于输入、前向和双向迭代器,他们使用++ 来提供线性时间实现。

    另请注意,从 C++11 开始,标准向 std::next 添加了一个参数,因此您可以使用它前进指定的数量(和 std::prev 类似)。与std::advance 的区别在于它返回修改后的迭代器(std::advance 没有),这在某些情况下可能很方便。

    【讨论】:

    • 另一方面,使用较少通用的代码会阻止您无意中悲观代码:毕竟使用列表容器进行大量“随机访问”可能不是一个好主意。
    【解决方案2】:

    这取决于你需要什么:

    如果您需要通用性,请使用std::advance(it,2)。如果有人出现并将您的std::vector 更改为std::list,代码仍然可以编译,即使现在推进需要线性时间而不是恒定时间。

    如果您需要性能,请使用it+=2。如果有人出现并将您的std::vector 更改为std::list,则代码将无法编译,并指出(可能带有有用的注释)一个严重的性能问题。

    【讨论】:

      【解决方案3】:

      这取决于迭代器。 it=it+5 如果受支持会更快(仅在随机访问迭代器上受支持)。如果你想推进一个能力较差的迭代器(例如一个前向迭代器或一个双向迭代器),那么你可以使用std::advance,但它会更慢,因为它实际上会遍历所有中间元素。

      【讨论】:

      • 你错了,标准规定 std::advance 对于随机访问序列是线性的:“复杂性:如果 InputIterator 是随机访问迭代器的模型,则为常数时间,否则为线性时间。”
      • std::advance 是随机访问迭代器的常数时间 (§24.3.4/1)。
      • 我认为随机访问迭代器不是这样——在这种情况下,std::advance 应该和 + 运算符一样高效。
      • @Kylotan:在使用随机访问迭代器时,std::advance 需要使用“+”,因此它的复杂性是恒定的。但它不能保证“同样高效”——尤其是如果你关闭优化,advance 可能会在+ 产生内联代码的情况下使用函数调用(例如,如果 vector::iterator 是一个简单的指针)。
      • @Jerry - 我想你在我发布之前发布了 - 我的评论是对 kbloom 的回应,但在重新阅读答案时,我认为措辞并不是那么好,因为它暗示std::advance 本质上是一个较慢的操作。
      【解决方案4】:

      std::advance 也适用于非随机迭代器,而+= 版本适用于随机访问序列(向量等)。

      【讨论】:

        【解决方案5】:

        std::adnvance 是通用的 - 如果您不总是知道底层容器的类型,它很有用 - 它适用于所有情况。

        然而它是高效的:std::advance 将在它传递一个 RandomAccessIterator 时进行优化(如来自 std::vector 的一个),并会增加 ForwardAccessIterator 循环中的迭代器(如 std::list 中的一个)。

        【讨论】:

          【解决方案6】:

          使用 std::advance。它同样高效(它使用迭代器特征来为随机访问迭代器进行迭代器添加),并且更通用,因为它也适用于其他类型的迭代器。

          【讨论】:

            【解决方案7】:

            如果您永远不会更改容器(而且您可能不会),请使用 +,因为它易于查看和理解,并且使代码不那么混乱。

            如果您想更改容器,或者如果您正在使用可能在各种容器类型上实例化的模板,请使用 Advance,因为它适用于任何东西。

            作为一般规则,我不担心更改容器类型,因为我发现当我必须更改容器类型时,我最终还是会重新访问使用该容器的所有地方,以确保我'我不做任何突然愚蠢的事情(比如从列表中间随机抽取元素)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-05-07
              • 2013-01-29
              • 2011-04-14
              • 1970-01-01
              • 1970-01-01
              • 2014-11-08
              • 2018-04-22
              • 2018-12-16
              相关资源
              最近更新 更多