为什么Scott Meyers建议更喜欢`iterator`到`const_iterator`

时间:2017-08-22 18:48:31

标签: c++ stl iterator

在他的有效STL一书的第26项中,Scott Meyers建议优先iterator而不是const_iterator。据我了解,他主要通过解释const_iterator不适用于inserterase等某些功能来证明这一点。

但这不是const_iterator的全部意义,它不允许修改容器吗?也许更重要的是,它允许您在代码中表达这一意图。

默认情况下,他不应该建议您使用const_iterator,只有在需要修改容器时才使用iterator

2 个答案:

答案 0 :(得分:3)

他在书中所说的理由是:

  

•某些版本的插入和擦除需要迭代器。如果你想   调用这些函数,你将不得不生成迭代器。   const和反向迭代器不会做

     

•无法将const迭代器隐式转换为迭代器,   以及项27中描述的用于生成迭代器的技术   来自const_iterator既不普遍适用也不保证   要有效率。

,非常重要,他继续说道:

  不要误以为这意味着const迭代器是无用的   一般来说。他们不是。它们对算法非常有用,   因为算法通常不关心它们是什么类型的迭代器   与...合作。只要它们属于适当的类别。 const迭代器   对于许多容器成员函数也是可接受的。它' S   只有某种形式的插入和擦除是挑剔的。

因此,与往常一样,它在很大程度上取决于背景和情况。

答案 1 :(得分:3)

简短的回答是,由于C ++ 11标准的改进,当使用STL的最新实现时,Meyers 认为const_iterator更可取。< / p>

在讨论他首先提出反const_iterator建议并解释变化的原因之前,我需要澄清一个误解。你写道:

  

不是const_iterator的整点,它不允许修改容器吗?

这是一个明智的假设,但实际上这并不是iterator的目的。正如迈耶斯在第三版 Effective C ++ 中所解释的那样(特别是在 C ++ 11之前编写):

  

声明const const就像声明一个指针T* const(即声明一个iterator指针):const T*是不允许的指向不同的东西,但它指向的东西可能会被修改。如果你想要一个指向无法修改的东西的迭代器(即const_iterator指针的STL模拟),你需要一个const_iterator [。]

简而言之,insert无法防止修改容器,它可以防止修改包含的值。这就是为什么Meyers希望const_iteratorerase兼容:它不会修改容器中已存在的任何元素。

const有点奇怪,因为它导致包含的元素被破坏,这是一个非erase操作。但请注意,元素的析构函数不是通过迭代器本身调用的;迭代器只是API提供给指定项目的手段const_iterator d。在语义上,iterator应该能够实现此目的以及const_iterator

现在,关于 Effective STL 中的建议及其随后的撤消,我将在这个问题上解释并引用一些 Effective Modern C ++ 。在第13项中,&#34;首选iteratorconst_iterators s&#34;,迈耶斯写道:

  

...在C ++ 98中,const_iterator只有半心半意的支持。创建它们并不容易,一旦你有了它,你可以使用它的方式是有限的....

     

...没有简单的方法从非const容器中获取const_iterator ...

     

一旦你有iterator s ...插入(和删除)的位置只能由const_iterator指定。 static_cast是不可接受的。

他举了一个例子,广泛使用const_iterator来解决这些限制,但指出,

  

...我所显示的代码也可能无法编译,因为没有iteratorstatic_cast的可移植转换,甚至没有reinterpret_cast 1}}。即使是被称为const_iterator的语义大锤也无法完成这项任务。

他总结道:

  

... cbegin在C ++ 98中遇到了很多麻烦,很少值得打扰。

这些问题由C ++ 11标准解决。正如对您的问题的评论中所提到的,此标准引入了cendconst_iterator,无论容器本身是否为const,它都会返回const_iterator。此外,inserterase获得了const_iterator的重载。这使得Any CPU更容易使用。