【问题标题】:Why does Scott Meyers recommend to prefer `iterator` to `const_iterator`为什么 Scott Meyers 建议更喜欢 `iterator` 而不是 `const_iterator`
【发布时间】:2018-01-31 04:02:01
【问题描述】:

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

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

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

【问题讨论】:

  • 这本书有多久了?不确定何时引入 cbegin 和 cend。
  • @Robinson:从 2001 年开始,它已经相当老了。
  • ...实际上,C++11 确实支持inserterase for const_iterator
  • @kyle 得到答复。
  • const_iterator 指定它不会修改它指向的对象——并不是说容器不会被修改

标签: c++ stl iterator


【解决方案1】:

简短的回答是,由于 C++11 标准的改进,Meyers确实认为const_iterators 在使用 STL 的最新实现时更可取。

不过,在讨论他提出反对const_iterator 建议的原因并解释发生了什么变化之前,我需要澄清一个误解。你写:

这不是const_iterator 的全部意义,它不允许修改容器吗?

这是一个合理的假设,但实际上这并不是const_iterator 的目的。正如 Meyers 在第三版 Effective C++ 中解释的那样(尤其是在C++11 之前编写):

声明iterator const 就像声明一个指针const(即声明一个T* const 指针):iterator 不允许指向不同的东西,但它指向的东西可以修改。如果您想要一个指向无法修改的东西的迭代器(即,const T* 指针的 STL 类似物),您需要一个 const_iterator[.]

简而言之,const_iterator 不能防止修改容器,它可以防止修改包含的值。这就是 Meyers 期望 insertconst_iterator 兼容的原因:它不会修改容器中已经存在的任何元素。

erase 有点陌生,因为它会导致一个包含的元素被销毁,这是一个非const 操作。但请注意,元素的析构函数不是通过迭代器本身调用的;迭代器只是 API 提供的用于指定项目为erased 的方法。从语义上讲,const_iteratoriterator 应该能够达到此目的。


现在,关于Effective STL 中的建议及其随后的撤回,我将转述并引用一些Effective Modern C++ 中的内容。在第 13 项“首选const_iterators 而非iterators”中,Meyers 写道:

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

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

一旦有了const_iterators...插入(和擦除)的位置,就只能由iterators 指定。 const_iterators 是不可接受的。

他举了一个广泛使用static_cast 来绕过这些限制的例子,但他指出,

...我展示的代码也可能无法编译,因为没有从const_iteratoriterator 的可移植转换,甚至没有static_cast。即使是被称为reinterpret_cast 的语义大锤也无法完成这项工作。

他总结道:

...const_iterators 在 C++98 中太麻烦了,几乎不值得费心。

C++11 标准解决了这些问题。正如在对您的问题的评论中提到的那样,该标准引入了cbegincend,无论容器本身是否为const,它们都会返回const_iterator。此外,inserterase 被赋予了const_iterator 的重载。这使得const_iterator 更易于使用。

【讨论】:

    【解决方案2】:

    他在书中所说的原因是:

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

    • 不能将 const 迭代器隐式转换为迭代器, 以及条款 27 中描述的用于生成迭代器的技术 来自 const_iterator 既不普遍适用也不保证 提高效率。

    但是,非常重要,他继续说:

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

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

    【讨论】:

    • 是的,但是我想知道他为什么根本没有提到我认为const_iterator存在的主要原因——表示迭代器不会修改容器。跨度>
    • 这个答案不完整;任何完整的答案都应参考 Meyers 在 Effective Modern C++ 中的论点,即“在 C++98 中,const_iterators 只有半心半意的支持”。
    猜你喜欢
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    相关资源
    最近更新 更多