2011-12-06 64 views
2

我迷路了:除非函数调用(Z_UB-> set())在++之前,std :: string向量的迭代器才能完美工作。下面的代码:C++迭代器随机失效

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-> 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->设置()函数,我创建迭代器后,访问它会使程序崩溃。我错过了关于迭代器的事情吗?

+2

这里没有足够的信息来诊断您的具体问题。迭代器不会“随机地”失效,所以问题出现在你的代码中,但是在你的代码中这个帖子里并不清楚问题所在。 'Z_UB'确实是'Parameter'类型的吗?还有其他什么类型的,可以修改底层'vector'的东西吗?在向量的内部存储器的大小调整过程中,矢量迭代器无效。 – Chad

+1

getVector()是否返回对矢量或副本的引用? –

+0

它返回的矢量副本(根据我没有使用&任何地方) – buhmann

回答

1

.getVector()返回了一个向量的副本。将迭代器与完全不同对象的迭代器的终点进行比较没有任何意义。返回参考解决了问题。

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

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

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

+1

这也是,返回的副本在创建迭代器的行的末尾立即销毁,因为迭代器立即失效并且您进入了未定义行为的区域。 – Xeo

1

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

+0

从示例代码这不是发生在这里... – Benoit

2

如果g_SPPglobal变量,那么它上面的迭代器将被任何变异操作无效化。


更新 - 这是自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),和

擦除无效的所有参考文献,迭代器和指针指的是初始擦除元件的位置后的元件。

  • 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 
    ; 
+0

有趣的是,你可以添加一个参考支持这个请吗? – Benoit

+0

通过变异你是指只添加和删除元素吗? –

2

几种可能性:

  • 要么你没有一个很好的reproductible例子:也许在你第一次运行在您的向量只有一个元素(它是如何填充的?),并调用未定义的行为,因为您没有检查it针对g_SPP.scenarios->getVector().end()
  • Z_UB->set不符合您的想法。它是一个多态类吗? set是虚拟的吗? ->运算符是否超载?
  • 您的应用程序是多线程的,而另一个线程正在改变您的容器?
+0

- > set函数被重载,但我添加了一些调试输出到所有其他版本。只有我希望运行的那个被调用。 – buhmann