c++学习之容器——erase()函数

本文深入分析了容器操作中的erase()函数,指出其返回值为被删除元素后的迭代器,并强调了使用后的迭代器可能产生的野指针问题。通过修改算法实现,确保数据顺序不会影响结果且避免野指针错误。文章提供了具体示例并讨论了容器操作中需要注意的关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


先介绍erase()函数的用法,erase()函数用于在顺序型容器中删除容器的一个元素,有两种函数原型,c.erase(p),c.erase(b,e);第一个删除迭代器p所指向的元素,第二个删除迭代器b,e所标记的范围内的元素,c为容器对象,返回值都是一个迭代器,该迭代器指向被删除元素后面的元素(这个是重点),具体的详细用法请参考其他资料。

这里就有一个问题,比如《c++ primer》习题9.26,该题目要求如下:

有一个数组int a[] ={0,1,1,2,3,5,8,13,21,55,89};要求将该数组保存到一个vector容器中和一个list容器中,然后将vector容器中的偶数删除,将list容器中的奇数删除,关于本题,该书课后答案核心代码如下:

	for(list<int>::iterator iter = ilst.begin();
			iter != ilst.end();iter++
			){
			if((*iter) %2 == 1){
			//	int tmp = *iter;
				iter = ilst.erase(iter);
				--iter;
			//	continue;
			}
		//	iter++;
	}
这个只是一段核心算法代码,基本上考虑到了该考虑的问题,比如说删除一个元素之后,指针指向该删除元素的后面一个元素,如果循环再加1,就跳过了被删除元素的下一个元素,但是存在一个很严重的问题,我们看Vertor段的代码:

	for(vector<int>::iterator iter = ivec.begin();
			iter != ivec.end(); iter++
			){
			if((*iter) %2 == 0){
		//		int tmp = *iter;
				iter = ivec.erase(iter);
				--iter;
		//		continue;
			}
		//	iter++;
	}
然后以第一个数据为例,删除了第一个元素0之后,返回的iter指向下一个元素1,然后做自减运算,这时就出现了问题,前面的元素0已经删除,这个时候自减运算得到的结果就是一个野指针,程序就会出现问题。也就是说上面的代码形式对不同的数据的顺序会产生不同的结果,可能会出错 ,这显然不是我们要的。所以我将代码改为如下形式:

	for(vector<int>::iterator iter = ivec.begin();
			iter != ivec.end(); //iter++
			){
			if((*iter) %2 == 0){
			//	int tmp = *iter;
				iter = ivec.erase(iter);
			//	--iter;
				continue;
			}
			iter++;
	}

以这样的形式,数据的顺序就不会影响结果,而且也不会出现野指针的问题,考虑到第二个erase()函数,我觉得对erase()函数的用法不能有太大的限制,我们在对容器操作,删除容器内元素,使用erase函数时,需要时刻记住的有两点:

第一个就是erase函数的返回值是一个指向被删除元素的下一个元素的迭代器。

第二点就是使用完erase函数之后的迭代器是否会产生野指针。这样的话在写代码的时候就不会产生很大的问题。

写这篇文章主要是发现网上关于容器的erase()函数介绍不够详细,如果有什么问题,欢迎批评指正。

### C++ `erase` 函数删除容器元素的用法 #### 使用 `std::vector` 的 `erase` 方法 在 C++ 中,`std::vector` 提供了一个名为 `erase` 的成员函数,允许用户通过迭代器指定要删除的位置或范围。以下是具体用法: - **单个元素删除** 当需要移除向量中的某个特定位置上的元素时,可以通过传递指向该元素的迭代器来实现。 ```cpp #include <iostream> #include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 删除第三个元素 (即值为3的元素) vec.erase(vec.begin() + 2); for(auto& elem : vec){ std::cout << elem << " "; } } // 输出: 1 2 4 5 [^2] ``` 上述代码展示了如何利用 `erase` 移除位于索引2处(注意:C++采用零基索引)的数值3。 - **多个连续元素删除** 如果目标是从向量中一次性清除一段连续区域内的所有项目,则需提供一对表示起始与终止边界的迭代器参数给 `erase`. ```cpp #include <iostream> #include <vector> int main(){ std::vector<int> numbers={0,1,2,3,4,5,6}; // 去掉第二个到第四个数(原数组下标分别为1至3对应的元素) numbers.erase(numbers.begin()+1 ,numbers.begin()+4); for(int num : numbers){ std::cout<<num<<" "; } } // 结果显示剩余项为: 0 4 5 6 [^2] ``` 此片段演示了怎样借助两个定位点之间的间隔消除一系列相连的数据条目。 #### 应用于字符串对象 (`std::string`) 上的情形 对于字符序列而言,同样存在相应的操作机制——调用其专属版本的 `erase()` 成员方法即可完成局部截断的任务。 - **基于位置偏移量执行剪裁** ```cpp #include <iostream> #include <string> using namespace std; int main () { string str ("Example String"); cout << "原始字符串:" << str << endl; // 自第五位开始抹去三个单位长度的内容 str.erase (7,8); cout << "修改后的字符串:"<<str<<endl ; return 0; } /* 预期输出如下所示: 原始字符串:Example String 修改后的字符串:Example */ [^3] ``` 这里体现了依据起点坐标以及预期影响跨度来进行部分剔除的过程。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值