代码之家  ›  专栏  ›  技术社区  ›  Frank

我应该更喜欢迭代器而不是常量迭代器吗?

  •  27
  • Frank  · 技术社区  · 15 年前

    最近这里有人 brought up Scott Meyers的文章说:

    • 喜欢 iterators 结束 const_iterators ( pdf link )

    有人评论说这篇文章可能过时了。我想知道你的意见是什么?

    这是我的:本文的一个要点是您不能在 const_iterator 但是我觉得用它来反对 迭代器 . 我认为 迭代器 您根本不修改范围,元素本身也不是通过替换它们的值来修改的,范围也不是通过插入或删除来修改的。还是我错过了什么?

    6 回复  |  直到 7 年前
        1
  •  22
  •   Gal Goldman    15 年前

    我完全同意你的看法。 我认为答案很简单: 使用常量迭代器,其中常量值是正确使用的,反之亦然。 在我看来,那些反对常量迭代器的人通常必须反对常量…

        2
  •  9
  •   D.Shawley    15 年前

    这里有一个稍微不同的方法来看待它。 Const_iterator 当您将它作为指针传递到特定集合时,几乎没有意义 你也在传递收藏。迈耶先生特别声明 const_iterator 不能与集合实例的大多数成员函数一起使用。那样的话,你就需要一个普通的 iterator . 但是,如果您没有集合的句柄,那么这两者之间的唯一区别就是您可以修改 指向 由一个 迭代器 并且不能修改 常数迭代器 .

    所以…你想用 迭代器 每当将集合和位置传递给算法时。基本上,签名如下:

    void some_operation(std::vector<int>& vec, std::vector::const_iterator pos);
    

    不太有道理。隐含的说法是 some_operation 可以自由修改基础集合,但不允许修改 pos 参考文献。这没什么意义。如果你真的想要这个,那么 销售时点情报系统 应该是偏移量而不是迭代器。

    另一方面,STL中的大多数算法都基于一对迭代器指定的范围。集合本身从未传递,因此 迭代器 常数迭代器 是否可以通过迭代器修改集合中的值。没有对集合的引用,分离就相当清晰。

    希望能让事情变得像泥一样清楚;)

        3
  •  3
  •   dirkgently    15 年前

    我不认为需要特别关注迈耶的这一特殊声明。当需要非修改操作时,最好使用 const_iterator . 否则,使用普通 iterator . 但是,请注意一件重要的事情:不要混合迭代器,即 const 那些有 non-const 那些。只要你知道后者,你就应该没事。

        4
  •  3
  •   Community holdenweb    7 年前

    我通常更喜欢常量,但最近遇到了一个难题,常量迭代器混淆了我的“总是使用常量是可能的”哲学:

    MyList::const_iterator find( const MyList & list, int identifier )
    {
        // do some stuff to find identifier
        return retConstItor;
    }
    

    由于传入const-list引用要求只使用const迭代器,所以现在如果使用find,就不能对结果执行任何操作,而是查看它,即使我只想执行express,find也不会更改正在传入的列表。

    那么,我想知道,斯科特·梅耶斯的建议是否与这样的问题有关,在这种情况下,逃避警察是不可能的。据我所知,你 不能 (可靠地)由于一些内部细节,使用简单的强制转换的un const const_迭代器。这也是(也许是结合在一起)的问题。

    这可能是相关的: How to remove constness of const_iterator?

        5
  •  2
  •   John Dibling    15 年前

    根据我对这个链接的理解,迈耶斯似乎从根本上说,交互程序比常量交互程序更好,因为您不能通过常量迭代器进行更改。

    但如果他是这么说的话,那么迈尔斯实际上是错的。这正是为什么当您想要表达时,const_迭代器优于迭代器的原因。

        6
  •  2
  •   DrSvanHay    7 年前

    C++ 98

    我认为需要考虑迈尔斯语句是指C++ 98。今天很难说,但如果我记得对的话

    • 对于一个非常量容器来说,获取一个常量迭代器是不容易的。
    • 如果你有一个常量迭代器,你几乎不能使用它,因为大多数(全部?)。容器成员函数的位置参数应为迭代器,而不是常量迭代器

    例如

    std::vector<int> container;
    

    可能需要

    static_cast<std::vector<int>::const_iterator>(container.begin())
    

    得到一个常量迭代器,它会大大膨胀一个简单的。 即使你有了结果

    std::vector<int>::const_iterator i = std::find(static_cast<std::vector<int>::const_iterator>(container.begin()), static_cast<std::vector<int>::const_iterator>(container.end()),42);
    

    没有办法使用std::vector::const_迭代器插入到vector或任何其他成员函数中,这些函数需要位置的迭代器。无法从常量迭代器中获取迭代器。不存在铸造方法(是否存在?)为此。

    因为const迭代器并不意味着容器不能被更改,而只意味着指向的元素不能被更改(const迭代器相当于指向const的指针) 在这种情况下,这真是一堆废话。

    今天情况正好相反。

    const迭代器很容易使用cbegin等,即使对于非const容器和all(?)采用位置的成员函数具有常量迭代器作为参数,因此不需要进行任何转换。

    std::vector<int> container;                
    auto i = std::find(container.cbegin(), container.cend(), 42); 
    container.insert(i, 43); 
    

    原来是什么

    优先使用迭代器而不是常量迭代器

    今天真的应该是

    比迭代器更喜欢常量迭代器

    因为第一个只是历史执行缺陷的产物。