Day13:C++之STL容器(1/3)

目录

一、定长数组array

0.实现原理(自己写的一个简易版本的array)

1.创建并初始化

2.常用函数及其他操作:

3.定长数组处理自定义类型的数据(比如wbm类):

4.用迭代器访问:(类中类iterator对象)

二、动态数组Vector

1.创建并插入data:

①不带长度的创建(原型参数中包含一个分配器,专门用来管理一些特殊的成员,例如文件指针,free来单独释放。类似的操作在后面的智能指针再去细讲)

②带长度

③带初始化的(直接赋值即可)(自动算出长度为3)

2.用迭代器的方式对vector容器进行遍历

3.自定义类型数据的vector存储

4.其他操作

三、array和vector的嵌套


一、定长数组array

0.实现原理(自己写的一个简易版本的array)

template <class _Ty,size_t size>
class MyArray 
{
public:
	MyArray() 
	{
		memroy = new _Ty[size];
		//new MM[size]
		
	}
	_Ty& operator[](int index)
	{
		return memroy[index];
	}
	~MyArray() 
	{
		delete[] memroy;
	}
public:
	_Ty* begin() 
	{
		return memroy + 0;
	}
	_Ty* end() 
	{
		return memroy + size;
	}
	//类的对象模仿指针的行为
	class iterator 
	{
	public:
		iterator(_Ty* pmove = nullptr) :pmove(pmove) {}
		void operator=(_Ty* pmove) 
		{
			this->pmove = pmove;
		}
		bool operator!=(_Ty* pmove) 
		{
			return this->pmove != pmove;
		}
		iterator operator++(int) 
		{
			this->pmove++;
			return *this;
		}
		_Ty operator*() 
		{
			return pmove[0];
		}
	protected:
		_Ty* pmove;
	};

protected:
	_Ty* memroy;	//MM
};
void testMyArray() 
{
	MyArray<int, 3> array1D;
	for (int i = 0; i < 3; i++) 
	{
		array1D[i] = i;
	}
	MyArray<int, 3>::iterator iter;
	for (iter = array1D.begin(); iter != array1D.end(); iter++) 
	{
		cout << *iter << "\t";
	}
	cout << endl;
}

1.创建并初始化

①不推荐new一个array对象出来,因为还需要自己自行释放,就直接用对象,其可以自行管理内存

②直接用数组下标法访问

本质是类模板,必须进行显式调用。

void testArray() 
{
	//存储数据的类型是:int  
    //数组长度:3
    //用模板的时候用的都是对象,而不是new一个对象
	array<int, 3> array1D;
	array<string, 3>* p = new array<string, 3>;
	delete p;
#define MAX 5
	array<double, 5> dAarray1D;
	//创建并初始化
	array<int, 3>  num = { 1,2,3 };
	for (int i = 0; i < array1D.size(); i++) 
	{
		array1D[i] = i;
	}
}

2.常用函数及其他操作:

empty():判断容器是否为空,和通过 size()==0 的判断条件功能相同,但其效率可能更快。

size():

fill():将容器中所有的元素填充为同一个数字。

迭代器for循环遍历的写法

swap()函数:需要长度一致。

void testExOperator() 
{
	//使用: 和数组一样的用法
	//一些函数
	array<int, 3> test = { 1,2,3 };
	cout << test.empty() << endl;
	cout << test.size() << endl;
	test.fill(5);		//填充所有的元素 ,填充为5
	for (int v : test)		
	{
		cout << v << "\t";
	}
	cout << endl;
	//交换  长度一定是要一样常
	array<int, 3> test1 = { 0,0,0};
	test.swap(test1);
	int cData[3] = { 1,2,3 };   //映射:一种对应关系,数组下标对应元素
	for (auto v : cData) 
	{
		cout << v << "\t";
	}
	cout << endl;
}

3.定长数组处理自定义类型的数据(比如wbm类):

①正常开一个定长自定义数据类型的array时,需要一个无参的构造函数(因为其内部实现用的new是无参构造方式)

②赋值时由于[ ]被重载了,可以采用方括号法来进行等于=赋值 ,在采用for(auto val: array名)遍历。

4.用迭代器访问:(类中类iterator对象)

begin()永远指向第一个元素的位置

end()指向最后一个元素后一个的位置(小心越界访问!!!)(一般采用*(迭代器名称.end()-1)来访问最后一个元素)

③用对象模仿指针的行为=>所以*号加上迭代器就是进行取值运算

迭代器进行遍历的方法。(可以用点运算符进行访问(需要加上*),也可以用箭头->来访问)

//定长数组处理自定义类型的数据
class MM
{
public:
	MM() {}
	MM(string name, int age) :name(name), age(age) {}
	void print() 
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
void testUserData() 
{
	array<MM, 3> mmData;	//	MM array[3];
	for (int i = 0; i < mmData.size(); i++) 
	{
		string name = "name";
		mmData[i] = MM(name + to_string(i), 16 + i);
	}

	for (auto v : mmData) 
	{
		//v:就是MM的对象
		v.print();
		//cout<<v;			//想要这样输出,重载<<运算符
	}
	//迭代器访问
	//对象模仿指针,*迭代器 就是取值运算
	array<MM, 3>::iterator iter;
	//begin()
	//end(): 最后一个位置,不是最后元素的位置
	(*mmData.begin()).print();
	//(*mmData.end()).print();  越界访问
	(*(mmData.end() - 1)).print();
	for (iter = mmData.begin(); iter != mmData.end(); iter++) 
	{
		//(*iter).print();
		iter->print();
		//cout<<*iter;		//重载<<
	}
}
//array当做函数参数,返回值都可以
array<int, 3>&  returnArray(array<int, 3>& temp) 
{
	for (int i = 0; i < temp.size(); i++)
	{
		temp[i] = i;
	}
	return temp;
}

二、动态数组Vector

1.创建并插入data:

①不带长度的创建(原型参数中包含一个分配器,专门用来管理一些特殊的成员,例如文件指针,free来单独释放。类似的操作在后面的智能指针再去细讲)

vector<int> vecDate;

这种方式,只能用成员函数做插入(尾插法

vector.push_back(666);

②带长度

vector<string> strDate(3);//默认为0

确定长度的好处:可以直接使用数组下标法插入(只有在确定长度范围以内才可以,若超过的必须采用成员函数进行插入)->否则vector subscript out of range(数组下标越界)可以在push_back在原内存的后面进行扩增。

for(int i=0;i<3;i++)
{
    string name="name";
    strDate[i]=name+to_string(i);
}

③带初始化的(直接赋值即可)(自动算出长度为3

vector<double> dDate={1.1,1.3,1.5};

2.用迭代器的方式对vector容器进行遍历

vector<string>::iterator iter;
for(iter=strData.begin();iter!=strData.end();iter++)
{
    cout<<*iter<<"\t";
}

3.自定义类型数据的vector存储

区别于array(不需要无参构造函数!!!)->所以在vector中可以先声明,但实际没有申请内存。

主要就是输入输出的时候需要进行重载一下。

4.其他操作

size(): 当前容器中元素的个数

empty(): 判断是否为空

front():访问第一个元素

back():访问最后一个元素

at(int i):利用下标访问  iDate.at(2)等效于 iDate[2];

emplace(参数1,参数2):修改函数,参数1参入应该是一个元素(‘地址’),参数2传入的是需要修改成的值

(正确写法)  //修改下标为2的值为100

vector<int> iDate={1,2,3,4};
iDate.emplace(iDate.begin()+2,100);

(错误写法)

vector<int> iDate={1,2,3,4};
iDate.emplace(&iDate[2],100);

没有进行相应的重载(别老想着当指针用了()所有的容器都是用迭代器来描述位置的。

emplace_back(参数):在尾部添加一个元素(扩增)

 注:无emplace_front()

删除函数

 ⑨批量复制assign()函数

int array[]={1,2,3};
vector<int> vecDate;//无需起始长度
vecDate.assign(array,array+3);

三、array和vector的嵌套

1.array和array的嵌套

void testArrayVsArray() 
{
	array<array<int, 3>, 4> arrData;  //int arrData[4][3]
	for (int i = 0; i < 4; i++) 
	{
		for (int j = 0; j < 3; j++) 
		{
			arrData[i][j] = i * j;
			cout << arrData[i][j] << "\t";
		}
		cout << endl;
	}
}

2.vector和vector的嵌套(通常用的push_back一个temp vector->可以生成不等列长的二维数组,所以遍历的时候常用size()) ()

void testVectorVsVector() 
{
	srand((unsigned int)time(nullptr));
	vector<vector<int>> vecData;
	//一般vecotor 采用的是push_back插入
	for (int i = 0; i < 4; i++) 
	{
		vector<int> temp;
		//rand()%3 [0,2]  [2,4]
		for (int j = 0; j < rand()%3+2; j++) 
		{
			temp.push_back(i * j);
		}
		vecData.push_back(temp);
	}
	//不等列数的二位数组
	for (int i = 0; i < vecData.size(); i++) 
	{
		for (int j = 0; j < vecData[i].size(); j++) 
		{
			cout << vecData[i][j] << "\t";
		}
		cout << endl;
	}
}

3.array中嵌套vector

void testArrayVsVector()
{
	array<vector<int>, 3> vecArr;
	vector<int> vec1[3] = { { 1,2,3 } , {1,2,3,4}, {1,2}};
	for (int i = 0; i < vecArr.size(); i++) 
	{
		vecArr[i] = vec1[i];
	}
	//不等列数的二位数组
	for (int i = 0; i < vecArr.size(); i++)
	{
		for (int j = 0; j < vecArr[i].size(); j++)
		{
			cout << vecArr[i][j] << "\t";
		}
		cout << endl;
	}
	vector<array<array<vector<int>, 3>, 3>> vec;
	//慢慢剥洋葱即可
	array<array<vector<int>, 3>, 3> test;
	for (int i = 0; i < 3; i++) 
	{
		test[i] = vecArr;		//vecArr: array<vector<int>, 3>
	}
	vec.push_back(test);
	
	vector<array<array<vector<int>, 3>, 3>> test;
	//上面一行 等效下面两行
	using Data = array<array<vector<int>, 3>, 3>;
	vector<Data> test2;

	array<array<vector<int>, 3>, 3> test3;
	//上面一行 等效下面两行
	using Data2 = array<vector<int>, 3>;
	array<Data2, 3>  test3;
}

4.vector中嵌套array(慢慢剥洋葱即可)(解析过程,可以用using语法起别名来理解简化)

using Date=array<.......>  实际开发中一般不会交叉嵌套,上限3层较多。

void testVectorVsArray() 
{
	vector<array<int, 3>> arrVec;
	array<int, 3>  arr[3] = { { 1,2,3 } , {1,2,3}, {1,2,3}};
	for (int i = 0; i < 3; i++) 
	{
		arrVec.push_back(arr[i]);
	}
	for (int i = 0; i < arrVec.size(); i++)
	{
		for (int j = 0; j < arrVec[i].size(); j++)
		{
			cout << arrVec[i][j] << "\t";
		}
		cout << endl;
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值