调试迭代器支持

Visual c + + 运行库检测到不正确使用的迭代器,并在运行时断言和显示一个对话框。 若要启用调试迭代器支持,必须使用 c + + 标准库和 C 运行库的调试版本来编译你的程序。 有关详细信息,请参阅 CRT 库功能。 有关如何使用经过检查的迭代器的信息,请参阅经过检查的迭代器

C++ 标准描述了成员函数可能会如何导致一个容器的迭代器无效。 两个示例包括:

  • 擦除容器中的元素会导致该元素的迭代器无效。

  • 通过使用推送或插入增加向量的大小会导致进入 vector 的迭代器无效。

迭代器无效

如果在调试模式下编译此示例程序,则在运行时它将断言并终止。

// iterator_debugging_0.cpp
// compile by using /EHsc /MDd
#include <vector>
#include <iostream>

int main() {
   std::vector<int> v {10, 15, 20};
   std::vector<int>::iterator i = v.begin();
   ++i;

   std::vector<int>::iterator j = v.end();
   --j;

   std::cout << *j << '\n';

   v.insert(i,25);

   std::cout << *j << '\n'; // Using an old iterator after an insert
}

使用 _ITERATOR_DEBUG_LEVEL

可以使用预处理器宏 _ITERATOR_DEBUG_LEVEL 关闭调试版本中迭代器的调试功能。 此程序不会断言,但仍会触发未定义的行为。

// iterator_debugging_1.cpp
// compile by using: /EHsc /MDd
#define _ITERATOR_DEBUG_LEVEL 0
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v {10, 15, 20};

   std::vector<int>::iterator i = v.begin();
   ++i;

   std::vector<int>::iterator j = v.end();
   --j;

   std::cout << *j << '\n';

   v.insert(i,25);

   std::cout << *j << '\n'; // Using an old iterator after an insert
}
20
-572662307

迭代器未初始化

如果在初始化之前尝试使用迭代器,断言也会发生,如下所示:

// iterator_debugging_2.cpp
// compile by using: /EHsc /MDd
#include <string>
using namespace std;

int main() {
   string::iterator i1, i2;
   if (i1 == i2)
      ;
}

迭代器不兼容

下面的代码示例引发断言,因为指向 for_each 算法的两个迭代器不兼容。 算法会执行检查以确定提供给它们的迭代器是否引用相同的容器。

// iterator_debugging_3.cpp
// compile by using /EHsc /MDd
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    vector<int> v1 {10, 20};
    vector<int> v2 {10, 20};

    // The next line asserts because v1 and v2 are
    // incompatible.
    for_each(v1.begin(), v2.end(), [] (int& elem) { elem *= 2; } );
}

请注意,本示例使用 lambda 表达式 [] (int& elem) { elem *= 2; } 而不是某个函数。 虽然此选项对于断言失败没有任何影响,类似函数会导致相同的故障,lambda 是一种编写短代码块的方法。 若要详细了解 lambda 表达式,请参阅 lambda 表达式

迭代器超出范围

for 循环作用域结束时,调试迭代器检查也会导致 for 循环中声明的迭代器变量超出范围。

// iterator_debugging_4.cpp
// compile by using: /EHsc /MDd
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v {10, 15, 20};

   for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i)
      ;   // do nothing
   --i;   // C2065
}

用于调试迭代器的析构函数

调试迭代器具有不平常的析构函数。 如果析构函数未运行,但对象的内存已释放,则可能会发生访问冲突和数据损坏。 请看以下示例:

// iterator_debugging_5.cpp
// compile by using: /EHsc /MDd
#include <vector>
struct base {
   // TO FIX: uncomment the next line
   // virtual ~base() {}
};

struct derived : base {
   std::vector<int>::iterator m_iter;
   derived( std::vector<int>::iterator iter ) : m_iter( iter ) {}
   ~derived() {}
};

int main() {
   std::vector<int> vect( 10 );
   base * pb = new derived( vect.begin() );
   delete pb;  // doesn't call ~derived()
   // access violation
}

另请参阅

C++ 标准库概述