c++ STL容器 --- 定长数组array

 包含头文件 <array>

 array<int, 3> array1D;
  • 是一个模板类

  • 存储的数据类型(数组的类型):int 

  • 数组的长度:3

  • 用模板时用的都是对象,而不是new一个对象→ 有效管理内存:创建对象,能自动释放内存

#include<array>
using namespace std;
//size_t: unsigned int 无符号整型
template <class _Ty, size_t size>
class MyArray
{
public:
	MyArray()                        //构造函数负责内存的申请
	{
		memory = new _Ty[size];      //new 一个_Ty类型的内存 大小为 size 需要有一个长度
								     //必须是常量不能是变量 new MM[size] 
	}
    _Ty& operator[](int index)
    {
        return memory[index];
    }
    ~MyArray()
    {
        delete[] memory;
    }
protected:
	_Ty* memory;  //内存
};
void testArray()
{
//创建不初始化
    MyArray<int, 3> array1D;
	array<int, 3> array1D;
	/*array<string, 3>* p = new array<string, 3>; new一个指针的方式,记得释放内存
	  delete p;*/
#define MAX 5
	array<double, MAX> dAarray1D;   //可以用宏的方式(符号常量),并且创建的时候可以做初始化操作
//创建并初始化
	array<int, 3>  num = { 1,2,3 }; //直接用等号赋值的方式初始化
	for (int i = 0; i < array1D.size()/*3*/; i++)    
	{
		array1D[i] = i;             //因为是定长数组,直接用数组下标法去访问
	}	
}
int main()
{
	testArray();
}

 小知识:

  • 容器统一不用指针去操作,而是用里面内置的迭代器去操作

  • array 数组和一维数组一样使用,只是它是一个模版类 (用类描述的数组)

封装的一些实用函数

void testExOperator() {
	//使用:和数组一样的用法
	//一些函数
	array<int, 3> test = { 1,2,3 };
    //判断是否为空的函数
	cout << test.empty() << endl;  
    //判断当前容器里面的元素个数
    cout << test.size() << endl;   
    //填充所有的元素为5,参数值:填充的数字
	test.fill(5);		           
    //对于容器的打印可以使用新版的 for 循环
    //让 v 指向第一个元素,从第一个元素开始遍历到最后一个元素
    //表示当前变量是对于容器的开始位置,自动做遍历 如果要修改容器中的元素,用引用
    for (/*auto*/int v : test) {         
		cout << v << "\t";
	}
}
int main() {
    testExOperator();
}
/*输出*/

0
3
5       5       5

 如果两个数组长度不同,能否交换?

void testExOperator() {
    //array<int, 3> test1 = { 0,0,0 }; 数组元素不写默认为0  
	array<int, 3> test;    
    //交换  长度一定要一样长 长度不同不能交换
    //array<int, 3> test1 = { 1,2,3,4,5 };
	array<int, 3> test1 = { 1,2,0 };
	test.swap(test1);
	for (auto v : test)
	{
		cout << v << "\t";
	}
	cout << endl;
}
int main() {
	testExOperator();
}
/*输出*/

1       2       0

 在c++中数组也可以算一种容器

void testExOperator() {
    //array 数组和普通数组没区别,创建方式不同而已  映射:一种对应关系,数组下标对应元素
	int cData[3] = { 1,2,3 }; 
    //同样可以用新版 for 打印
    for (auto v : cData)    
	{
		cout << v << "\t";
	}
	cout << endl;
}

int main() {
	testExOperator();
}
/*输出*/

1       2       3

array 数组处理基本数据类型,直接创建,把数据放进去即可,和普通数组一样使用

定长数组处理自定义类型的数据

class MM
{
public:
    //需要准备一个无参的构造函数
	MM() {}                                            
    //这个 array 管理 MM 类型的数据怎么处理?
	MM(string name, int age) :name(name), age(age) {}  
	void print() 
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
void testUserData() 
{
    //MM array[3]; 报错:无法引用 std::array<MM,3U> 的默认构造函数-> 它是已删除的函数
	array<MM, 3> mmData;          
    //用下标法访问          
	for (int i = 0; i < mmData.size(); i++) 
	{
		string name = "name";
        //对象 + 下标的方式 因为重载了[]构造无参对象,to_string 把下标 i 转换成字符串 
		mmData[i] = MM(name + to_string(i), 16 + i); 
	}    
    //遍历
	for (auto v : mmData) 
	{
		//v:MM的对象 对象调用成员函数的方式    
		v.print();
		//cout<<v;   想要这样输出,需要重载 << 运算符
	}
	
}
int main() {
    testUserData();
}

/*注意*/

/*array<MM, 3> mmData;不能传一个参数,等效创建MM array[3]这样的
  3个数组,这里面存的是 3 个 MM 类型的对象*/ 

/*输出*/

name0   16
name1   17
name2   18

为啥要准备无参的构造函数?

class MyArray
{
public:
    //构造函数负责内存的申请
	MyArray()     
	{
        /*memory=new MM[size]; 传入MM类型的数据,类似类的组合,在new一个指针出来时,如果传入自定义类型,需要调用无参构造函数*/
		memory = new _Ty[size]; 
	}
protected:
    //内存
	_Ty* memory;  
};

/* new一个数组出来,一定是无参构造方式 */

/*因为管理的是任意类型,所以标准库中也不能确定这个参数(管理数据类型不同,构造函数的
形态也不一样) 无参构造函数每个类中都有,无论你写几个参数的构造函数-> 在构造对象时,
使用的方式是无参构造方式*/

用迭代器访问 ---> 类中类

用 array 类中类 iterator 定义一个对象 iter

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;   
    array<MM, 3>::iterator iter;
    //用对象调用成员函数的方式打印第一个元素(对象)       
	(*mmData.begin()).print();  
	(*(mmData.end() - 1)).print();
    //下标法访问
    for (int i = 0; i < mmData.size(); i++) 
	{
		string name = "name";
        /*对象+下标的方式,因为重载了[]构造无参对象,to_string 把下标i转换成字符串*/
		mmData[i] = MM(name + to_string(i), 16 + i); 
	}    
    //把迭代器赋值成某个元素开始的位置 当迭代器不等于容器结束的位置
	for (iter = mmData.begin(); iter != mmData.end(); iter++) 
	{
		iter->print();    //iter是对象的地址,用指针指向运算符访问 迭代器模仿指针的行为
        (*iter).print();  //对象调用成员函数的方式  
		//cout<<*iter;    //重载 <<
	}
}
int main() {
    testUserData();
}

begin():容器的第一个位置
  end():最后一个位置的下一个位置,是结束位置,不是最后一个元素的位置
(*mmData.end()).print();  注意不要越界访问  最后一个位置的上一个位置才是最后一个元素的位置

name0   16
name2   18
name0   16
name1   17
name2   18

 

模拟一个迭代器、一个array数组

迭代器的访问方式,对象模仿指针的行为,用法和指针一样,可做+ +运算

  • * 指针    →取值

  • * 迭代器→取值

template <class _Ty,size_t size>
class MyArray 
{
public:
	MyArray() 
	{
		memroy = new _Ty[size];
		//new MM[size]	
	}
	_Ty& operator[](int index)    //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()                      //自己写的array数组,标准库中增加了很多成员函数
{
	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;
}

array类的对象和普通类的对象用法没区别,类的对象能干嘛,它就能干嘛

可以当做函数参数,也可以当作返回值

//返回数组的函数-> 返回一个迭代器,如果想修改这个容器,传这个容器的引用即可
array<int, 3>& returnArray(array<int, 3>& temp)
{
	for (int i = 0; i < temp.size(); i++)
	{
		temp[i] = i;
	}
	return temp;
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qiuqiuyaq

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

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

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

打赏作者

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

抵扣说明:

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

余额充值