1.主要实现的功能
- 直接初始化
- 构造函数
- 深拷贝
- 返回长度
- 追加元素
- 移动赋值
2.代码
#include <iostream>
using namespace std;
template<class T>
class vector
{
private:
int sz; //数组已用长度
T* elem; //指向元素的指针
int space; //已用大小+空闲空间
public:
vector(initializer_list<T>lst) :sz{ lst.size() }, elem{ new T[sz] } //实现 vector<int>v = {1,3}这种初始化赋值操作
{
copy(lst.begin(), lst.end(), elem);
}
vector() : sz{ 0 }, elem{ nullptr }, space{ 0 } {} //默认构造函数
vector(const vector<T>&arg) :sz{ arg.sz }, elem{ new T[arg.sz] } //拷贝构造函数实现深拷贝
{
copy(arg.elem, arg.elem + arg.sz, elem);
}
vector& operator = (const vector& a); //拷贝赋值
explicit vector(int s) :sz{ s }, elem{ new T[s] } //单参数的构造函数加explicit防止隐式赋值
{
for (int i = 0; i < sz; i++)
elem[i] = 0;
}
~vector(){ delete[] elem; } //析构函数
T & operator[](int i) //运算符重载实现v[i]=5这种形式,引用为了返回一个地址
{
if (i > sz)
{
cout << "越界访问了" << endl;
}
return elem[i];
}
const T operator[](int n) const //给const vector<T>s这种形式用的
{
return elem[n];
}
int size() const{ return sz; } //返回vector长度
vector(vector&& a) //移动构造函数
{
a.sz = 0;
a.elem = nullptr;
}
vector& operator = (vector&&) //移动赋值
{
delete[] elem;
elem = a.elem;
sz = a.sz;
a.elem = nullptr;
a.sz = 0;
return *this;
}
int capacity() const { return space; } //总空间大小
void reserve(int newalloc); //增加空间
void resize(int newsize); //改变长度
void push_back(const T&d);
};
template<class T>
void vector<T>::reserve(int newalloc) //newalloc是新的长度
{
if (newalloc <= space) return;
T* p = new T[newalloc];
for (int i = 0; i < sz; i++) p[i] = elem[i];
delete[]elem;
elem = p;
space = newalloc;
}
template<class T>
void vector<T>::resize(int newsize)
{
reserve(newsize);
for (int i = sz; i<newsize; ++i) elem[i] = 0; //初始化新元素
sz = newsize;
}
template<class T>
void vector<T>::push_back(const T&d)
{
if (space == 0)
reserve(sizeof(d));
else if (space == sz)
reserve(2 * space);
elem[sz] = d; //添加元素
++sz; //更新长度
}
template <class T>
typename vector<T>& vector<T>::operator=(const vector<T>& a)//拷贝赋值
{
if (this == &a) return *this; // 自我赋值毫无意义
if (a.sz <= space) { // space足够,不用分配新空间
for (int i = 0; i < a.sz; ++i) elem[i] = a.elem[i]; // 直接拷贝元素就行
sz = a.sz;
return *this;
}
T* p = new T[a.sz]; // 分配新元素
for (int i = 0; i < a.sz; ++i) p[i] = a.elem[i]; // 拷贝元素
delete[] elem; // 释放旧空间
space = sz = a.sz; // 设置新大小
elem = p; // 设置新元素指针
return *this; // 返回自引用
}
int main()
{
vector<int>v(3);
vector<int>v2 = v;
vector<int>k = { 1, 3};
cout << v2[0] << endl;
v.push_back(3);
cout << v.size() << endl;
cout << k.size() << endl;
return 0;
}
3.注意事项
- 单参数构造函数要用explict,用来防止隐式转换例子如下
#include<iostream>
using namespace std;
class Test1
{
public:
Test1(int n)
{
num = n;
}//普通构造函数
private:
int num;
};
class Test2
{
public:
explicit Test2(int n)
{
num = n;
}//explicit(显式)构造函数
private:
int num;
};
int main()
{
Test1 t1 = 12;//隐式调用其构造函数,成功
Test2 t2 = 12;//编译错误,不能隐式调用其构造函数
Test2 t2(12);//显式调用成功
return 0;
}
2.如果没有拷贝构造函数,两个vector赋值时默认浅拷贝将会指向同一片地址,删除一个对象另一个也被删除
3.成员函数声明在类里面,定义在类外,template 类型 函数名:: 这种形式, 模板参数和成员函数所在的类模板参数一样,template
typename vector& vector::operator=(const vector& a)//拷贝赋值,这个有点特殊因为返回值类型是自定义的vector,typename表明后面的vector是个类型
4.拷贝构造函数在对象初始化时才会调用,在定义了对象以后如果对象间再赋值就是调用重载的=号