C++迭代器随机失效
我迷路了: std::string 向量的迭代器可以完美工作,除非在 it++ 之前有函数调用 (Z_UB->set() )。这是代码:
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->set() 函数,则访问它将使程序崩溃。关于迭代器,我是否遗漏了一些重要的东西?
I'm lost: An iterator of a vector of std::string works perfectly unless there is a function call (Z_UB->set() ) before it++. Here's the code:
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;
creates the following output
begin of vector: scn1
However, if I move the function call like this:
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);
The result is the following, which is the expected behaviour:
begin of vector: scn1
second of vector: scn2
Inside the Z_UB->set() function there is nothing left but the call itself:
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;
}
So if I call the Z_UB->set() function after I created the iterator, accessing it will crash the program. Is there anything vital that I missed about Iterators?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
几种可能性:
g_SPP.scenarios->getVector().end()
Z_UB->set
不会按照你的想法做。它是一个多态类吗?set
是虚拟的吗?->
运算符是否重载?Several possibilities:
it
againstg_SPP.scenarios->getVector().end()
Z_UB->set
does not do what you think. Is it a polymorphic class? Isset
virtual? Is the->
operator overloaded?如果
g_SPP
是一个全局变量,那么任何变异操作都会使其上的迭代器失效。更新 - 这是来自 1998 年 ISO/ANSI 规范:
如果需要分配,以下内容会使引用序列元素的所有引用、迭代器和指针无效。如果当前
capacity()
小于目标向量大小,则需要进行分配。void Reserve(size_type n)
迭代器插入(迭代器位置,const T& x)
,void insert(迭代器位置,size_type n, const T& x)< /code>、
void insert(iteratorposition,InputIteratorfirst、InputIteratorlast)
和Erasure 使引用初始擦除位置之后的元素的所有引用、迭代器和指针无效 元素。
迭代器擦除(迭代器位置)
迭代器擦除(迭代器第一个,迭代器第二个)
调整向量大小相当于调用
insert
或erase
。根据 23.2.4.2/6:resize(sz, c=value_type())
具有与以下相同的效果:If
g_SPP
is a global variable then iterators over it will be invalidated by any mutating operation.Update -- this is from the 1998 ISO/ANSI spec:
The following invalidate all references, iterators, and pointers referring to elements of the sequence if an allocation is required. An allocation is required if the current
capacity()
is less than the target vector size.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)
, andErasure invalidates all references, iterators, and pointers referring to elements after the position of the initial erased element.
iterator erase(iterator position)
iterator erase(iterator first, iterator second)
Resizing a vector is equivalent to calling either
insert
orerase
. According to 23.2.4.2/6:resize(sz, c=value_type())
has the same effect as:如果在迭代时添加或删除元素,或者在添加元素时向量需要在内部调整自身大小,则 std::vector::iterator 将会失效。
a
std::vector<T>::iterator
will be invalidated if you add or remove elements while iterating over it, if the vector needs to resize itself internally, when an element is added..getVector() 返回向量的副本。将迭代器与完全不同对象的迭代器的终点进行比较是没有意义的。返回参考解决了这个问题。
@Xeo 还指出了一个更好的解释:当从这样的副本创建迭代器时:
副本立即被销毁,从而使刚刚创建的迭代器无效。所以迭代器不应该首先返回第一个元素,但我只能猜测这深深地隐藏在编译器的实现中。
.getVector() returned a copy of the vector. Comparing an iterator to the end point of the iterator of a completely different object doesn't make sense. Returning a reference solved the problem.
@Xeo also pointed out a much better explanation: When creating an iterator from a copy like this:
the copy immediately is destroyed thus invalidating the just created iterator. So the iterator shouldn't have returned the first element in the first place, but I can merely guess that this is hidden deeply in the implementation of the compiler.