我应该比const_iterators更喜欢迭代器吗?

时间:2009-04-19 11:28:13

标签: c++ stl iterator const-iterator

最近有人brought up来自Scott Meyers的文章说:

  • 首选iterators const_iteratorspdf link)。

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

这是我的:本文的要点之一是你无法删除或插入const_iterator,但我认为将其用作反对const_iterators的论据是很有趣的。我认为const_iterators它的全部要点是你根本不修改范围,也不是通过插入或删除来替换它们的值和范围。或者我错过了什么?

6 个答案:

答案 0 :(得分:22)

我完全同意你的看法。 我认为答案很简单: 使用const_iterators,其中const值是正确的使用方法,反之亦然。 在我看来,那些反对const_iterators的人一般都要反对const ......

答案 1 :(得分:9)

这是一种略微不同的方式来看待它。当你将它作为指向特定集合的指针传递给你时,Const_iterator几乎没有意义。 Meyer先生特别指出const_iterator不能与集合实例的大多数成员函数一起使用。在这种情况下,您需要一个普通的iterator。但是,如果您没有集合的句柄,那么两者之间的唯一区别是您可以修改iterator指向的内容,并且您无法修改const_iterator引用的对象。

所以...当你将集合和位置传递给算法时,你想要使用iterator。基本上,签名如:

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

没有多大意义。隐式语句是some_operation可以自由修改底层集合,但不允许修改pos引用。这没有多大意义。如果你真的想要这个,那么pos应该是一个偏移而不是一个迭代器。

另一方面,STL中的大多数算法都基于一对迭代器指定的范围。集合本身永远不会传递,因此iteratorconst_iterator之间的区别在于是否可以通过迭代器修改集合中的值。没有参考集合,分离是非常清楚的。

希望这能让事情像泥一样清晰;)

答案 2 :(得分:3)

我认为Meyer的这一特殊声明并不需要特别关注。如果需要非修改操作,最好使用const_iterator。否则,请使用普通的iterator。但是,请注意一件重要的事情:永远不要混用迭代器,即const个和non-const的迭代器。只要你知道后者,你应该没事。

答案 3 :(得分:3)

我通常更喜欢constness,但最近遇到了一个const_iterators的难题,这让我的“总是使用const是可能的”哲学感到困惑:

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

由于传入一个const列表引用需要我只使用const迭代器,现在如果我使用find,我不能对结果做任何事情但看看它即使我想做的只是表达发现不会改变传入的列表。

那么,我想,如果斯科特梅耶斯的建议与这样的问题有关,那么就不可能逃脱常规。根据我的理解,由于一些内部细节,你不能(可靠)un-const const_iterators与简单的强制转换。这也(也许是结合起来)是问题。

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

答案 4 :(得分:2)

通过阅读该链接,Meyers似乎从根本上说interator比const_interator更好,因为你无法通过const_iterator进行更改。

但如果这就是他所说的,那么迈耶斯其实是错的。这正是为什么当你想要表达的时候,const_iterator比迭代器更好的原因。

答案 5 :(得分:2)

C ++ 98

我认为需要考虑到Meyers声明引用c ++ 98。今天很难说,但如果我没记错的话

  • 根本不容易为非const容器获取const_iterator
  • 如果你有一个const_iterator你几乎不能使用它,因为容器成员函数的大多数(所有?)位置参数都应该是迭代器而不是const_iterators

e.g。

std::vector<int> container;

需要

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

得到一个const_iterator,这会大大夸大一个简单的.find

之后,即使你有了结果
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_iterator插入向量或任何其他预期位置迭代器的成员函数。并且无法从const迭代器获取迭代器。没有任何方法可以存在(存在吗?)。

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

今天情况恰恰相反。

使用cbegin等很容易获得const迭代器,即使对于非const容器也是如此,所有采用位置的(?)成员函数都将const迭代器作为参数,因此不需要任何转换。

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

那曾经是什么

  

优先于const_iterators的迭代器

今天真的应该是

  

首选const_iterators而不是迭代器

因为第一个只是历史实施缺陷的工件。