C ++迭代器随机失效

时间:2011-12-06 16:09:54

标签: c++ function iterator call invalidation

我迷路了:除非在++之前有一个函数调用(Z_UB-> set()),否则std :: string向量的迭代器工作得很好。这是代码:

std::vector< std::string >::iterator it = g_SPP.scenarios->getVector().begin();
std::cout << "begin of vector: " << *it << std::endl;
Z_UB->set("s1", "scn2", 350);
it++;
std::cout << "second of vector: " << *it << std::endl;

创建以下输出

begin of vector: scn1

但是,如果我像这样移动函数调用:

std::vector< std::string >::iterator it = g_SPP.scenarios->getVector().begin();
std::cout << "begin of vector: " << *it << std::endl;
it++;
std::cout << "second of vector: " << *it << std::endl;
Z_UB->set("s1", "scn2", 350);

结果如下,这是预期的行为:

begin of vector: scn1
second of vector: scn2

在Z_UB-&gt; set()函数内部,除了调用本身之外什么都没有留下:

void Parameter::set( std::string _i, std::string _j, float value) {
//int i = indexSets[0]->backIndex(_i);
//int j = indexSets[1]->backIndex(_j);

//data2D[0][0] = value;
}

因此,如果在创建迭代器后调用Z_UB-&gt; set()函数,访问它将使程序崩溃。有没有什么重要的我错过了迭代器?

4 个答案:

答案 0 :(得分:2)

如果g_SPP全局变量,则任何变异操作都会使其上的迭代器失效。


更新 - 这是1998 ISO / ANSI规范:

如果需要分配,以下内容将引用序列元素的所有引用,迭代器和指针无效。如果当前capacity()小于目标矢量大小,则需要进行分配。

  • void reserve(size_type n)
  • iterator insert(iterator position, const T& x)
  • void insert(iterator position, size_type n, const T& x)
  • void insert(iterator position, InputIterator first, InputIterator last)

Erasure使所有引用,迭代器和指针在初始擦除元素的位置之后引用元素无效。

  • iterator erase(iterator position)
  • iterator erase(iterator first, iterator second)

调整向量大小相当于调用inserterase。根据23.2.4.2/6:resize(sz, c=value_type())具有与以下相同的效果:

if (sz > size())
    insert(end(), sz - size(), c);
else if (sz < size())
    erase(begin() + sz, end());
else
    ;

答案 1 :(得分:2)

几种可能性:

  • 要么你没有一个好的可复制的例子:也许在你的第一次运行中你的向量中只有一个元素(如何填充?),并调用未定义的行为,因为你没有检查it对{ {1}}
  • g_SPP.scenarios->getVector().end()没有按照您的想法行事。它是一个多态类吗? Z_UB->set是虚拟的吗? set运算符是否已重载?
  • 您的应用是多线程的,另一个线程是否正在改变您的容器?

答案 2 :(得分:1)

如果在迭代时添加或删除元素,如果向量需要在内部调整自身大小,添加元素时,std::vector<T>::iterator将失效。

答案 3 :(得分:1)

.getVector()返回了矢量的副本。将迭代器与完全不同的对象的迭代器的终点进行比较是没有意义的。返回引用解决了问题。

@Xeo还指出了一个更好的解释:从这样的副本创建迭代器时:

std::vector< std::string >::iterator it = g_SPP.scenarios->getVector().begin();

立即销毁副本,从而使刚创建的迭代器无效。所以迭代器不应该首先返回第一个元素,但我只能猜测这是隐藏在编译器实现中的。