【C++】关于STL容器删除erase问题

对于容器vector、set

最近在看阿秀的八股文pdf时发现一条似乎有点问题,于是做了实验,以vector和set为例,这两个容器的erase函数都会返回下一个元素的迭代器,但是顺序容器vector确实不能使用erase(it++),此时it指向的并不是被删元素的下一个元素,具体可见下面的代码
在这里插入图片描述

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
using namespace std;


#include <vector>
#include <set>

void printSet(set<int>& s)
{
    
    
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}

//插入和删除
void test02()
{
    
    

	set<int> s1;
	//插入
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	printSet(s1);

	//删除
	auto k = s1.begin();
	auto k1 = s1.erase(k++);
	cout << *k << endl;
	cout << *k1 << endl;
	printSet(s1);


	//清空
	//s1.erase(s1.begin(), s1.end());
	s1.clear();
	printSet(s1);
}

void printVector(vector<int>& v) {
    
    

	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    
    
		cout << *it << " ";
	}
	cout << endl;
}

//插入和删除
void test01()
{
    
    
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	printVector(v1);

	//删除
	auto k = v1.begin();
	auto k1=v1.erase(k++);
	cout << *k << endl;
	cout << *k1 << endl;
	printVector(v1);

	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);
}

int main() {
    
    
	cout << endl;
	cout << "----------------Vector--------------" << endl;
	test01();
	cout << "----------------Set--------------" << endl;

	test02();


	system("pause");

	return 0;
}

输出结果如下:
第三行输出的时erase容器的返回迭代器所指向的元素,可以发现都是20,这个都没问题,但是vector的k却指向错误

----------------Vector--------------
10 20 30 40 
30
20
20 30 40 

----------------Set--------------
10 20 30 40 
20
20
20 30 40 

本来以为失效后,这个迭代器应该指向一个未知数,结果指向的是30,后来又做了新的实验,把test01改为下面的代码:
k指向30,利用erase删除30这个值

void test01()
{
    
    
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	printVector(v1);

	//删除
	auto k = v1.begin();
	k++;
	auto k1=v1.erase(k++);
	cout << *k << endl;
	cout << *k1 << endl;
	printVector(v1);

	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);
}

结果如下

----------------Vector--------------
10 20 30 40 
40
30
10 30 40 

----------------Set--------------
10 20 30 40 
20
20
20 30 40 

发现使用erase后k总会指向被删除元素的后面的后面的位置,此时指向的都是合法的位置,继续更改代码,将k指向30,再利用erase删除,test01代码如下:

void test01()
{
    
    
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	printVector(v1);

	//删除
	auto k = v1.begin();
	k++;
	k++;
	cout << "before erase k=" << *k << endl;
	auto k1=v1.erase(k++);
	cout << "after erase k=" << *k << endl;
	cout << *k1 << endl;
	printVector(v1);

	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);
}

结果如下:

----------------Vector--------------
10 20 30 40 
before erase k=30
after erase k=40
40
10 20 40 

----------------Set--------------
10 20 30 40 
20
20
20 30 40 

很奇怪,为什么还是指向最后一个数,继续++,再做实验,此时test01代码更改如下:

void test01()
{
    
    
	vector<int> v1;
	//尾插
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	printVector(v1);

	//删除
	auto k = v1.begin();
	k++;
	k++;
	k++;
	cout << "before erase k=" << *k << endl;
	auto k1=v1.erase(k++);
	cout << "after erase k=" << *k << endl;
	cout << *k1 << endl;
	printVector(v1);

	//清空
	v1.erase(v1.begin(), v1.end());
	v1.clear();
	printVector(v1);
}

结果如下:

----------------Vector--------------
10 20 30 40 
before erase k=40
after erase k=0
40
10 20 30 

----------------Set--------------
10 20 30 40 
20
20
20 30 40 

总结:顺序容器使用erase之后后面的迭代器都会失效,所以在今后写代码时需要多注意下,而关联式容器只是被删除的元素的迭代器失效,后面的迭代器还是可以用的

猜你喜欢

转载自blog.csdn.net/qq_43050258/article/details/129994053