容器的空间配置器
容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。
例子:
Vector:
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
Vector 底层已经封装好了增删查改
void reserve(int size); // 预留函数
void push_back(const T &val); // 末尾添加元素
void pop_back(); // 末尾删除元素
bool empty()const; // 判空
bool full()const; // 判满
reserve只开空间 但是没有放东西进去
resize不仅给vector容器开辟size个空间,还放了size个东西进去了
出现空间配置器的原因
1.在开辟空间时,用new来构造对象会增加大量的无效对象.
所以应该把对象的内存开辟和对象构造分开 不能直接用new new 开辟内存 调用构造函数
class A
{
public:
A() {
cout << "A()" << endl; }
~A() {
cout << "~A()" << endl; }
};
int main()
{
vector<int> intvec(20);//默认开辟20个空间 还调用了构造函数 但是我们只要空间的其实
return 0;
}
2.在添加元素的时候应当是拷贝构造,而不是赋值重载(赋值重载是因为本来就存在了对象)
3.删除元素的时候不光是把指针–,还得把last指向的对象进行析构
4.在容器销毁时,析构的应当是有效对象,而不是把我构造出来的没用到的对象也析构掉了.
所以应该把对象的析构和内存释放分开 不能直接用delete delete先调用析构函数 再释放内存(free)
template<typename T>
void Vector<T>::reserve(int size)//预留函数
{
if (size <= msize)
return;
T *ptmp = new T[size];
for (int i = 0; i < mcur; ++i)
{
ptmp[i] = mpvec[i];
}
delete[]mpvec;
mpvec = ptmp;
msize = size;
}
... ...
int main()
{
// C++ STL 组件之一:容器
Test t1, t2, t3;
cout << "------------" << endl;
Vector<Test> vec;
vec.reserve(10); // 只想预留空间 不想创建那么多的对象
cout << "------------" << endl;
vec.push_back(t1);//添加元素想构造 而不是赋值操作
vec.push_back(std::move(t2));
vec.push_back(t3);
cout << "------------" << endl;
vec.pop_back();
cout << "------------" << endl;
解决方法:
1.destory()
从容器删除对象的时候要析构,但不能用delete,用destory(),指针指向的对象,调用它的析构.
容器有多少个元素就析构多少个(+i是要往后移动,mpvec就是首元素的地址)
template<typename T>
Vector<T>::~Vector()
{
for (int i = 0; i < mcur; ++i)
{
// 析构容器中有效的对象
malloctor.destroy(mpvec+i);
}
// 把容器内存释放掉
malloctor.deallocate(mpvec);
mpvec = nullptr;
}
2.construct()
在一个开辟好的内存上构造一个对象(这样就可以实现拷贝构造而不是赋值重载)
// 自定义一个容器的空间配置器
template<typename T>
struct myallocator
{
// 内存开辟
T* allocate(size_t size)
{