最近在看C++标准程序库的时候,发现书上的一段代码在vc2005中发生runtime error,代码段如下:
vector<int> vecInt;
for ( int i = 0; i < 10; i++ )
{
vecInt.push_back( i );
}
vecInt.reserve( vecInt.size() * 2);
copy( vecInt.begin(), vecInt.end(), back_inserter(vecInt));
跟进代码发现 原因是copy函数中会去比较InputIterator start和InputIterator end的值( posfrom != posEnd ), 此时调用vector_const_iteratator的operator==函数,在此函数中vc会调用一个名为_Compat的验证函数, 其中语句if (this->_Mycont == 0 || this->_Mycont != _Right._Mycont)验证失败而抛出异常。_Mycont是一个container base类型,貌似其中保存了iterator的head ptr。跟了一下代码,导致异常的原因是当back_inserter第一次调用push_back插入元素时,插入的位置正是end()迭代器所在的位置!在debug模式下运行,vector::push_back会调用_Orphan_range(_Mylast, _Mylast), 这就将end() 位置无效化。以release运行此代码没有问题。此段代码是书上的源代码,
以下代码也会产生同样的错误:
vector<int> vecInt;
vecInt.reserve( 100 );
vector<int>::iterator posS = vecInt.begin();
vector<int>::iterator posE = vecInt.end();
vecInt.push_back( 100 );
posS != posE; //cause exception
简单的说,就是在push_back操作时使迭代器失效了(只限于debug版本,因为release版本不会调用_Orphan_range(_Mylast, _Mylast) ). 书上说push_back本来不会引起迭代器失效,因为是在尾部插入,但debug版的vc就会让end()失效。相比之下,SGISTL的vector::iterator貌似就直接用指针实现的,比较简单;而vc的iterator是实现了一个新类型,要复杂一点。