C++vector里面的各种函数,C++vector创建二维数组,迭代器的失效问题

本文详细介绍了C++标准模板库中的Vector容器使用方法,包括创建、初始化、扩容、迭代器失效等问题,并提供了丰富的代码示例。

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


可以简单的将vector想象成一个可扩容的线性表
在这里插入图片描述

vector创建二维数组

1,直接创建;

//M行N列的二维数组
vector<vector<int>>arr(M,vector<int>(N));

2,利用扩容函数;

vector<vector<int>>arr;
arr.resize(M);
for(int i=0;i<M;i++)
{
 arr[i].resize(N);
}

vector的初始化

int main()
{
	int ar[] = { 12,23,34 };
	vector<int>ar1;
	vector<int>ar2 = {12,23,34,45,56};
	vector<int>ar3(10, 23);
	vector<int>ar4({ 12,23,34,45,56 });
	vector<int>ar5(ar1);
	vector<int>ar6(std::move(ar2));
	ar1 = { 12,23,34,45 };
	//ar1 = ar;erro
	ar1 = std::move(ar3);
	return 0;
}
int main()
{
	vector<Object> objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	return 0;
}

先构建4个对象,然后在vector里面拷贝构造
在这里插入图片描述

在这里插入图片描述

通过迭代器对vector里面的数据进行访问

#include<vector>
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x) { cout << "Object" << endl; }
	Object(const Object& obj) :value(obj.value) { cout << "Object &" << endl; }
	Object(Object&& obj) :value(obj.value) { cout << "move Object&&" << endl; }
	Object& operator=(const Object& obj)
	{
		value = obj.value;
		cout << "operator=" << endl;
		return *this;
	}
	Object& operator=(const Object&& obj)
	{
		value = obj.value;
		cout << "operator=" << endl;
		return *this;
	}
	~Object()
	{
		cout << "~Object" << endl;
	}
	int& Value()
	{
		return value;
	}
};

int main()
{
	vector<Object> objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	for (int i = 0; i < objvec.size(); ++i)
	{
		cout << objvec[i].Value() << endl;
	}
	for (int i = 0; i < objvec.capacity(); ++i)
	{
		cout << objvec.at(i).Value() << endl;
	}
	vector<Object>::iterator it = objvec.begin();
	for (; it != objvec.end(); ++it)
	{//迭代器里面已经对->和*进行了运算符的重载
		cout << it->Value() << " " << (*it).Value() << endl;
	}
	it = objvec.begin();
	for (; it != objvec.end(); ++it)
	{
		cout << it->Value() << " " << endl;
		it->Value() += 100;
		cout << (*it).Value() << " "<< endl;
	}
	//如果不想让迭代器改变值用常性迭代器
	vector<Object>::const_iterator cit = objvec.begin();
	//const int *p;p++;
	for (; cit != objvec.end(); ++cit)
	{
		//cout << cit->Value()<< endl;erro长迭代器不能调用普通的方法
	    //两种解决办法1,将迭代器改为非常性;
	    //2,在类里面在设计一个常性方法
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	for (auto x : objvec)//推演出x是Object类型而不是iterator
	{
		cout << x.Value() << endl;
	}
	return  0;
}

在这里插入图片描述

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	//for (auto x : objvec)//推演出x是Object类型而不是iterator
	//{
	//	cout << x.Value() << endl;
	//}
	//不希望更改value就加const
	//没有好坏之分只有程序员的需求
	for (const auto &x : objvec)//推演出x是Object类型而不是iterator
	{
		cout << x.Value() << endl;
	}
	return  0;
}

在这里插入图片描述

//不建议这样写
int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	Object* op = objvec.data();
	cout << op->Value() << endl;
	op->Value() += 10;
	op->~Object();
	delete[]op;
}

reserve

#include<vector>
class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x) { cout << "Object" << endl; }
	Object(const Object& obj) :value(obj.value) { cout << "Object &" << endl; }
	Object(Object&& obj) :value(obj.value) { cout << "move Object&&" << endl; }
	Object& operator=(const Object& obj)
	{
		value = obj.value;
		cout << "operator=" << endl;
		return *this;
	}
	Object& operator=(const Object&& obj)
	{
		value = obj.value;
		cout << "operator=" << endl;
		return *this;
	}
	~Object()
	{
		cout << "~Object" << endl;
	}
	int& Value()
	{
		return value;
	}
};

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	objvec.reserve(10);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}

在这里插入图片描述
在这里插入图片描述

扩容导致迭代器失效

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	vector<Object>::iterator it = objvec.begin();
	Object& obj = objvec.back();
	objvec.reserve(10);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}

![

resize

在这里插入图片描述

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	/*vector<Object>::iterator it = objvec.begin();
	Object& obj = objvec.back();
	objvec.reserve(10);*/
	objvec.resize(10);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}

在这里插入图片描述
在这里插入图片描述

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	/*vector<Object>::iterator it = objvec.begin();
	Object& obj = objvec.back();
	objvec.reserve(10);*/
	objvec.resize(10);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	objvec.resize(2);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}
int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
initializer_list<Object>arr = { Object(10),Object(20) };
	//c11
	int a{ 10 };
	int* p{ nullptr };
	int ar[]{ 12,23,34 };
	vector<int>veci{ 12,23,34 };
	list<int>ilist{ 12,23,34,45 };


	/*vector<Object>::iterator it = objvec.begin();
	Object& obj = objvec.back();
	objvec.reserve(10);*/
	objvec.resize(10);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}

列表方式初始化

#include<initializer_list>
template<class T>
class SeqList
{
	T* data;
	int maxsize;
	int cursize;
public:
	SeqList(int sz = 10) :data(T new[sz], maxsize(sz), cursize(sz)) {}
	SeqList(std::initializer_list<T>init)
	{
		maxsize = init.size();
		cursize = maxsize;
		data = (T*)malloc(sizeof(T) * maxsize);
	}
};

int main()
{
	SeqList<int>seqlist{ 12,23,34,45 };
	return 0;
}

assign

注意这几种扩容均可能导致迭代器失效

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	//objvec.reserve(10);//容量的扩张,不能收缩
	//objvec.resize(10);//size()=>不仅能扩容,还能增加对象的数量
	//objvec.resize(2);//size()=>不能收缩空间,但是能减少对象的个数
	for (auto& x : objvec)
	{
		cout << x.Value() << endl;
	}
	objvec.assign(10, Object(100));
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	for (auto& x : objvec)
	{
		cout << x.Value() << endl;
	}
}

在这里插入图片描述
在这里插入图片描述

reserve(1000)空间太大可用空间过多如何处理

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	objvec.reserve(100000);
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	{//tmp的生存期只在{}里面
		vector<Object>tmp(objvec);
		tmp.swap(objvec);
		//交换只交换first.last,end
	}
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
}

在这里插入图片描述

在这里插入图片描述

插入函数

push_back

push_back(100);是隐士构造,先创建无名对象object在对其拷贝构造,注意这里只有在单参构造函数里面才可以,如果你想拒绝隐士构建在但参构造函数前加explicit

int main()
{
		vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
		cout << objvec.size() << endl;
		cout << objvec.capacity() << endl;
		vector<Object>::iterator it = objvec.begin();
		cout << it->Value() << endl;
		objvec.push_back(Object(100));
		cout << it->Value() << endl;
}

插入函数可能会导致迭代器失效
在这里插入图片描述

insert函数

int main()
{
	vector<Object>objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	vector<Object>::iterator it = objvec.begin();
	objvec.insert(it,Object(20));//在头部插入(类似顺序表)效率很低
	//objvec.insert(it,{Object(100),Object(200)});
	return 0;
}

emplace_back()原位构建

int main()
{
	vector<Object>objvec;
	objvec.reserve(10);
	objvec = { Object(10),Object(20),Object(30),Object(40) };
	cout << objvec.size() << endl;
	cout << objvec.capacity() << endl;
	//objvec.push_back(Object(10));这样先构建无名对象,在给vector里面移动构造,在析构无名对象而原位构建直接构建
  //objvec.push_back(10);隐士构建
	objvec.emplace_back(100);
}

在这里插入图片描述

在这里插入图片描述

template<class T,class ...Arg>
void Make(T* p, Arg... arg)
{
	new(p) T(arg...);
	
}
int main()
{
	Object* p = (Object*)malloc(sizeof(Object));
	Object obj(12);
	Make(p, 12);
	Make(p, 12, 23);
	Make(p, std::move(obj));
}

在这里插入图片描述
在这里插入图片描述

迭代器的失效问题

a:当容器调用erase方法后,当前位置到容器末尾元素的所有的迭代器全部失效了
b:当容器调用insert方法后,当前位置到容器末尾元素的所有的迭代器全部失效了
c:对于insert插入来说,如果引起容器内存扩容,那么原来容器的所有的迭代器就全部失效了
d:不同容器的迭代器是不能进行比较运算的
迭代器失效了以后,问题该怎么解决?
对插入/删除点的迭代器进行更新操作

我们发现:erase和insert都会返回一个新的迭代器。给当前位置插入元素或者删除元素,当前元素的后边元素都会发生移动,指向当前元素的迭代器就失效了。
当我们增加或者删除操作,会把操作完的当前位置的新的迭代器返回。
(生成当前位置的合法的迭代器并返回)
我们用it去接收返回的更新的迭代器。
我们删除了元素以后,后边的元素都会前移,所以it就不要++了
我们现在来解决插入元素的问题
插入一个元素,就把原当前位置的元素都后移了。
所以我们的it还要再多执行1次++了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值