数组类模板(c++)
分析:
①函数声明和定义分别写在头文件和源文件中,出现链接错误;查看资料:被多个源文件引用的函数模板,应当把函数体一同放在头文件中,不能像普通普通函数一样只将声明放在头文件中。
②深复制与浅复制:系统默认生成的复制构造函数实现的是浅复制,浅复制是指将对应的数据成员一 一赋值;当数据成员是指针类型时,且该指针值是数组首地址时,浅复制只能将首地址赋值给另外一个同类型指针,两个指针指向同一个内存单元,并没有构造自己的数组来存放数组元素,这样在析构时,同一段内存单元会释放两次,出错。因此,这种情况应该使用深复制,即构造对象自己的数组,并将数组中的元素一 一赋值,这样两个对象的指针数据成员各自指向自己的内存单元。
③左值与右值:左值在内存中有确定位置的对象,右值则相反;例如:a[0]=1,此时a[0]就是左值,它的值可以被改变。
关于左值右值:添加链接描述
④如果一个函数返回的是对象的引用,那么该对象的值是左值,因为引用是对象的别名,在使用时可以改变其值,例如c++中重载 ‘[]’ 、’=‘运算符时,返回的是对象的引用,因为a[i] = n和(a=b)++表达式都是允许的,而’+'是返回对象的值,因为 a+b=c 这样的表达式是不允许的。如果一个函数返回的是对象的值,它不应该作为左值。
#ifndef ARRAY_H
#define ARRAY_H
#include <cassert>
template <class T>
class Array
{
private:
T *list;//存放数组首地址
int size;
public:
Array(int size=50);
Array(const Array &a);
~Array();
Array& operator =(const Array &a);
T& operator [](int n);
operator T*();
int getSize() const;
void resize(int sz);
};
//构造函数
template <class T>
Array<T>::Array(int size)
{
assert(size>=0);
this->size=size;
list=new T[size];
}
//复制构造函数
template <class T>
Array<T>::Array(const Array<T> &a)
{
size=a.getSize();
list=new T[size];
for(int i=0; i<size; i++)
list[i]=a.list[i];
}
//析构函数
template <class T>
Array<T>::~Array()
{
delete[] list;
size=0;
}
//重载赋值运算符
template <class T>
Array<T>& Array<T>::operator =(const Array<T> &a)
{
if(this != &a)
{
if(size != a.getSize())
{
size=getSize();
delete[] list;
list = new T[size];
}
for(int i=0; i<size; i++)
list[i]=a.list[i];
}
return *this;
}
//重载下标运算符
template <class T>
T& Array<T>::operator [](int n)
{
assert(n>=0 && n<size);
return list[n];
}
//重载到T*类型的转换
template <class T>
Array<T>::operator T*()
{
return list;
}
//获取数组大小
template <class T>
int Array<T>::getSize() const
{
return size;
}
//修改数组大小
template <class T>
void Array<T>::resize(int sz)
{
assert(sz>=0);
if(size != sz)
{
int n=size<sz? size:sz;
T *temp=new T[sz];
for(int i=0; i<n; i++)
temp[i]=list[i];
delete[] list;
size=sz;
list=temp;
}
}
#endif