包含头文件 <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;
}