C++ STL如何在erase()之后保存迭代器
我想处理C++ STL如何在erase()之后保存迭代器,c++,stl,C++,Stl,我想处理向量容器中的每个节点 假设向量包含0、1、2和3,迭代器指向2 我想在不丢失迭代器位置信息的情况下删除2,因为我想在删除2之后处理“3” 下面是我所做的,但是输出没有显示我的意图 以下是我的问题: Q1)当vector::iterator oldIter=iter时被执行, oldIter是否创建新的迭代器对象 Q2)为什么迭代器的值在递增后保持不变 Q3)擦除节点而不丢失数据的好方法是什么 迭代器的位置 问题4)最后,一个无关紧要的问题。我试过了 当vector::iterator o
向量
容器中的每个节点
vector::iterator oldIter=iter时代码>被执行,
oldIter
是否创建新的迭代器对象
Q2)为什么迭代器的值在递增后保持不变
Q3)擦除节点而不丢失数据的好方法是什么
迭代器的位置
问题4)最后,一个无关紧要的问题。我试过了
当vector::iterator oldIter=iter时代码>被执行,oldIter是否执行
创建一个新的迭代器对象
对
为什么迭代器的值在递增后保持不变
是吗
没有。是什么让你得出这样的结论?您的printf
语句?那些是无效的printf
不知道如何处理向量迭代器。您对它的调用是未定义的行为
在不丢失节点位置的情况下擦除节点的好方法是什么
迭代器
捕获erase
调用的返回值
iter = vContainer.erase(iter);
最后,一个无关紧要的问题。我试过了
当vector::iterator oldIter=iter时代码>被执行,oldIter是否执行
创建一个新的迭代器对象
对
为什么迭代器的值在递增后保持不变
是吗
没有。是什么让你得出这样的结论?您的printf
语句?那些是无效的printf
不知道如何处理向量迭代器。您对它的调用是未定义的行为
在不丢失节点位置的情况下擦除节点的好方法是什么
迭代器
捕获erase
调用的返回值
iter = vContainer.erase(iter);
最后,一个无关紧要的问题。我尝试过cout理想情况下,不要单独删除节点。相反,将std::remove_if()
与std::vector::erase()
结合使用:这将潜在的二次算法转化为线性算法。也就是说,你会用这样的东西
vContainer.erase(std::remove_if(vContainer.begin(),
vContainer.end(),
[](int value){ return someCondition(value); }),
vContainer.end());
否则,最简单的方法可能是仅使用偏移恢复位置:
int offset(std::distance(vContainer.begin(), it));
vContainer.erase(it);
it = vContainer.begin() + offset;
由于erase(it)
将移动位置it
之后的所有对象,因此成本相当高。使用像std::remove_if()
这样的算法,最多只聚合更改并移动每个元素一次,而不是每次erase()
移动一次,这样的算法效率要高得多
针对您的具体问题:
std::vector::iterator oldIter=iter
显然创建了iter
的副本。但是,请注意,当使用erase(it)
时,引用it
引用的对象或该对象之后的所有迭代器都将无效
当递增迭代器时,它不会停留在同一位置。如果您认为是这样,那么您可能错误地确定了迭代器的位置。确定随机访问迭代器的迭代器位置的最佳方法是获取从序列开始的偏移量,例如,使用std::distance(v.begin(),it)
(假设it
是范围v.begin()
到v.end()
的迭代器)
只需保留从起点开始的偏移量并将其恢复即可
迭代器无法打印。他们的价值毫无意义。使用printf()
打印某些内容并不意味着什么,因为类型%x
只能用于整数值,并且在特定位置与其他类型一起使用它是未定义的行为。请参见上文如何获得迭代器位置的合理指示。请注意,std::distance(v.begin(),it)
的结果是某种积分类型:最好使用IOStreams打印它,IOStreams会自动计算出类型,而不是猜测printf()的格式说明符的类型
理想情况下,不要单独删除节点。相反,将std::remove_if()
与std::vector::erase()
结合使用:这将潜在的二次算法转化为线性算法。也就是说,你会用这样的东西
vContainer.erase(std::remove_if(vContainer.begin(),
vContainer.end(),
[](int value){ return someCondition(value); }),
vContainer.end());
否则,最简单的方法可能是仅使用偏移恢复位置:
int offset(std::distance(vContainer.begin(), it));
vContainer.erase(it);
it = vContainer.begin() + offset;
由于erase(it)
将移动位置it
之后的所有对象,因此成本相当高。使用像std::remove_if()
这样的算法,最多只聚合更改并移动每个元素一次,而不是每次erase()
移动一次,这样的算法效率要高得多
针对您的具体问题:
std::vector::iterator oldIter=iter
显然创建了iter
的副本。但是,请注意,当使用erase(it)
时,引用it
引用的对象或该对象之后的所有迭代器都将无效
当递增迭代器时,它不会停留在同一位置。如果您认为是这样,那么您可能错误地确定了迭代器的位置。确定随机访问迭代器的迭代器位置的最佳方法是获取从序列开始的偏移量,例如,使用std::distance(v.begin(),it)
(假设it
是范围v.begin()
到v.end()
的迭代器)
只需保留从起点开始的偏移量并将其恢复即可
迭代器无法打印。他们的价值毫无意义。使用printf()
打印某些内容这一事实并不意味着什么,因为类型%x
只能用于整数值并使用不同的类型