目录
(2)模板类定长array数组容器,可适用用户定义的数据类型
①变长类数组模板类不需要非通用类型参数,数组大小用成员变量表示,数组动态分配
②构造函数从主函数接收一个整型数据,用于初始化数组,动态分配数组空间Vector,并修改len
分类
①定长数组:array容器(C++11标准)
②可变数组:vector容器
③类模板的非通用类型参数
一、定长数组:array容器(C++11标准)
(1)普通类的定长array容器,只适用整型
代码
#include<iostream>
using namespace std;
#define MAXLEN 10
class Array
{
private:
int items[MAXLEN];
public:
Array(){memset(items,0,sizeof(items));
}
~Array(){
}//这个类没有用到堆区内存,析构函数什么都不做
//在函数中可以判断数组下标ii的合法性
int& operator[](int ii){return items[ii];}//重载操作符[],形参是数组下标,可以修改数组中的元素
const int& operator[](int ii)const{return items[ii];}//重载操作符[],形参是数组下标,不可以修改数组中的元素
};
int main()
{
Array aa;//创建模板类Array的对象
aa[0]=5;aa[1]=8;aa[2]=3;aa[3]=2;aa[4]=7;
for(int ii=0;ii<5;ii++)cout<<"a["<<ii<<"]="<<aa[ii]<<endl;
return 0;
}
运行结果
注意事项
这个类没有用到堆区(动态分配),用的是栈区,在执行析构函数时系统会自动释放空间,所以析构函数的函数体什么也不做;
(2)模板类定长array数组容器,可适用用户定义的数据类型
代码
#include<iostream>
using namespace std;
#define MAXLEN 10
template <class T>
class Array
{
private:
T items[MAXLEN];
public:
Array(){memset(items,0,sizeof(items));
}
~Array(){
}//这个类没有用到堆区内存,析构函数什么都不做
//在函数中可以判断数组下标ii的合法性
T& operator[](int ii){return items[ii];}//重载操作符[],形参是数组下标,可以修改数组中的元素
const T& operator[](int ii)const{return items[ii];}//重载操作符[],形参是数组下标,不可以修改数组中的元素
};
int main()
{
Array<int>aa;//创建模板类Array的对象
aa[0]=5;aa[1]=8;aa[2]=3;aa[3]=2;aa[4]=7;
for(int ii=0;ii<5;ii++)cout<<"a["<<ii<<"]="<<aa[ii]<<endl;
return 0;
}
调试步骤
①在类声明前面加上类模板的标志
template <class T>
②修改类当中用到的数据类型
运行结果
(3)带非通用类型参数的定长array数组容器
代码
#include<iostream>
#include<string.h>
using namespace std;
template <class T,int len=10>//非通用类型参数,可以有缺省值
class Array
{
private:
T items[len];
public:
Array(){memset(items,0,sizeof(items));
}
~Array(){
}//这个类没有用到堆区内存,析构函数什么都不做
//在函数中可以判断数组下标ii的合法性
T& operator[](int ii){return items[ii];}//重载操作符[],形参是数组下标,可以修改数组中的元素
const T& operator[](int ii)const{return items[ii];}//重载操作符[],形参是数组下标,不可以修改数组中的元素
};
int main()
{
Array<string,5>aa;//创建模板类Array的对象,需要指定非通用类型参数的值,因为有缺省值也可以不写
//aa[0]=5;aa[1]=8;aa[2]=3;aa[3]=2;aa[4]=7;
aa[0]="张三";aa[1]="李四";aa[2]="王五";aa[3]="老六";aa[4]="小七";
for(int ii=0;ii<5;ii++)cout<<"a["<<ii<<"]="<<aa[ii]<<endl;
return 0;
}
调试步骤
①去掉宏定义,使用非通用参数类型类模板
template <class T,int len=10>//可以有缺省值
②创建类对象时指定非通用参数类型模板
Array<string,5>aa;//也可以不指定,因为有缺省值
运行结果
注意细节
1)通常时整型(C++20标准后可以);
2)实例化模板时必须用常量表达式;
3)模板中不能修改参数的值;
优点
在栈上分配内存,容易维护,执行速度快,适合小数组
缺点
在程序中,不同的非通用类型参数将导致编译器生成不同的类
二、可变数组:vector容器
代码
#include<iostream>
#include<string.h>
using namespace std;
template <class T>
class Vector
{
private:
int len; //数组大小用成员变量表示
T *items; //数组元素用指针,动态分配
public:
Vector(int size=10):len(size){ //构造函数,把数组大小传入,分配内存
items=new T[len];
}
~Vector(){ //析构函数
delete[]items;items=NULL; //释放数组空间,指针置为空
}
void resize(int size){ //扩展数组的内存空间
if(size<=len)return; //只能往更大的扩展
T*tmp=new T[size]; //分配更大的目标数组
for(int ii=0;ii<len;ii++) //将原来的数组赋给目标数组
tmp[ii]=items[ii];
delete[]items; //释放原来的数组
items=tmp; //让数组指向新的目标数组
len=size;
}
int size()const{ //获取数组长度
return len;
}
T& operator[](int ii){ //重载操作符[],形参是数组下标,可以修改数组中的元素
if(ii>=len)resize(ii+10); //扩展数组空间
return items[ii];
}
const T& operator[](int ii)const{
return items[ii]; //重载操作符[],形参是数组下标,不可以修改数组中的元素
}
};
int main()
{
//Array<string,10>aa;//创建模板类Array的对象,需要指定非通用类型参数的值
//aa[0]=5;aa[1]=8;aa[2]=3;aa[3]=2;aa[4]=7;
Vector<string>aa(1);
aa[0]="张三";aa[1]="李四";aa[2]="王五";aa[3]="老六";aa[4]="小七";
for(int ii=0;ii<5;ii++)cout<<"a["<<ii<<"]="<<aa[ii]<<endl;
return 0;
}
调试步骤
①变长类数组模板类不需要非通用类型参数,数组大小用成员变量表示,数组动态分配
int len; //数组大小用成员变量表示
T *items; //数组元素用指针,动态分
②构造函数从主函数接收一个整型数据,用于初始化数组,动态分配数组空间Vector,并修改len
Vector(int size=10):len(size){ //构造函数,把数组大小传入,分配内存
items=new T[len];
}
③增加一个扩展数组大小的函数
void resize(int size){ //扩展数组的内存空间
if(size<=len)return; //只能往更大的扩展
T*tmp=new T[size]; //分配更大的目标数组
for(int ii=0;ii<len;ii++) //将原来的数组赋给目标数组
tmp[ii]=items[ii];
delete[]items; //释放原来的数组
items=tmp; //让数组指向新的目标数组
len=size;
}
④重载[ ]访问数组函数,增加扩展数组空间功能
T& operator[](int ii){ //重载操作符[],形参是数组下标,可以修改数组中的元素
if(ii>=len)resize(ii+10); //扩展数组空间
return items[ii];
}
运行结果
优点
虽然Vector容器效率不如Array容器,但是更通用,还可以自动扩展大小,也不会存在Array容器创建多个类的定义的情况;