65.9K
CodeProject 正在变化。 阅读更多。
Home

已检查的迭代器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (30投票s)

2007 年 2 月 24 日

3分钟阅读

viewsIcon

88109

关于 C++ 已检查迭代器的一些常见问题解答。

引言

我了解已检查迭代器已经有一段时间了,但在 Microsoft Visual C++ 2005 发布之前,我从未真正费心去使用或更好地理解它。它甚至在发布模式下都带有一个已检查版本的标准库,并且在从其他编译器移植代码时,我实际看到了使用已检查迭代器的好与坏。在使用已检查迭代器一年并对该主题进行了一些研究后,我觉得现在是与 Code Project 社区分享我收集到的知识的好时机。本文以一系列问题和答案的形式组织,力求简短易懂。

问答

什么是已检查迭代器?

已检查迭代器提供对容器和其他范围的已检查访问。它们通常知道拥有容器,并且能够捕获一些运行时错误,这些错误通常会导致未定义的行为,然后执行一些定义良好的操作,例如抛出异常或终止应用程序。这在避免与安全相关的问题(例如堆栈和堆溢出)方面特别有用。

已检查迭代器可以检测到哪些类型的错误?

这实际上取决于它们的实现。它们可以捕获的一些常见错误是

未初始化的迭代器

vector<int>::iterator it;
it++;     

超出范围的访问

vector<int>::iterator it = vec.end();
it++;      

比较来自不同范围或容器的迭代器

for (it = vec1.begin(); it != vec2.end(); ++it)     

已检查迭代器可以检测其他类型的错误,例如容器/范围内的无效数据吗?

是的。例如,UTF-8 CPP 库 2.0 或更高版本具有已检查的迭代器适配器,能够检测无效的 utf-8 序列

utf8::iterator<std::string::iterator> it(u8string.begin(), 
                                         u8string.begin(), u8string.end());
it++; // throws an exception in case of an invalid utf-8 sequence

请注意,我们将有效范围边界作为参数传递给了迭代器适配器的构造函数。

也有已检查的容器吗?如果有,它们有什么用?

正如已检查的迭代器跟踪它们的容器一样,容器也可以跟踪迭代器。这使得可以捕获诸如使用无效或“悬空”迭代器之类的错误

vector<int> it = vec.begin();
vec.clear();
it++;     

有没有简单的方法将未检查的迭代器转换为已检查的迭代器?

取决于。 像 Dinkumware 和 STLPort 这样的某些 STL 实现提供已检查和未检查的版本,并且在它们之间切换只是将特定宏设置为所需值的问题。 如果您想在调试模式下使用已检查的迭代器,而在发布模式下使用未检查的迭代器,这将特别方便,这是一个非常常见的方案。

除此之外,您可以编写一个已检查的迭代器适配器,将未检查的迭代器转换为已检查的迭代器。 在他的经典著作The C++ Programming Language中,Bjarne Stroustrup 给出了这样一个迭代器适配器的例子。 一般来说,它可以声明为类似

template <typename base_iterator, typename container_type>
class checked_iterator;     

并且像这样使用

checked_iterator<myvectype::iterator, myvectype> it (vecit, vec);
it++; // checked

当然,对于一个成熟的已检查 STL 实现来说,这样的适配器只是一个穷人的替代品,但仍然可能非常有用。

使用已检查的迭代器有什么缺点吗?

有 - 性能。 已检查的迭代器比未检查的迭代器更大更慢,并且速度差异(很少是内存占用)可能很显着。 有时最好仅在开发和第一轮测试期间使用已检查的迭代器,然后发布带有未检查的迭代器的软件,但这实际上取决于具体情况。

Microsoft Visual C++ 带有已检查的迭代器吗?

是的。 在 8.0 版 (VC++ 2005) 中,默认情况下会检查迭代器和容器,即使在发布版本中也是如此。 要关闭已检查的迭代器,必须将 _SECURE_SCL 宏设置为 0。 默认情况下,如果检测到错误,程序会通过调用 invalid_parameter 终止。 可以通过将 _SECURE_SCL_THROWS 设置为 1 来更改此行为,在这种情况下,如果发生错误,已检查的迭代器会抛出标准异常。

结论

已检查的迭代器是一个您应该了解并适当使用的工具,至少在开发期间应该如此。

参考文献

  1. Bjarne Stroustrup: The C++ Programming Language.
  2. Herb Sutter, Andrei Alexandrescu: C++ 编码标准.
  3. MSDN Library: 已检查的迭代器
© . All rights reserved.