Allocator容器实现自己的vector
-
网上版本的几个错误点
目前网站上大多数和https://www.cnblogs.com/bournet/p/4382089.html网站上一样,主要错误点有两个
1)resize函数重新更改的大小小于原始的size,应该是将多余的空间调用析构函数但并不销毁原始内存
2)reserve函数若重新分配的大小n若小于等于原始的capacity则不作任何处理,实际在vs和ubuntu下测试vector和string均是此结果(C++ primer第五版318页)。需要注意的是当n大于原始的capacity时:string的reserve函数在windows下按n*16-1分配,ubuntu下按照n重新分配;而vector均是按照重分配的n。这也符合《c++ primer》的原话“reserve至少分配与需求一样大的空间”
3)另外shrink_to_fit()函数原话也是“并不一定保证退回内存空间”,经过测试string:windows和ubuntu下容量只是部分减少,而vector则是size=capacity -
基本知识点
allocator容器需要引入#include<memory>头文件,与new/delete最大的不同就是构造和初始化是分开的,具体函数及步骤如下:
1、声明一个变量allocator<T> alloc;
2、分配原始内存返回指针T* test=alloc.allocate(n);
3、初始化分配的内存
for(size_t i=0;i<n;i++) { //注意此处调用的是拷贝构造函数初始化内存 alloc.construct(test+i,T()); }
4、使用完以后需要先析构
for(size_t i=0;i<n;i++) { //注意此处调用类的析构函数 alloc.destroy(test+i); }
5、`销毁分配的原始内存alloc.deconstruct(alloc,n)
- 实际代码如下
为了验证是否调用析构函数,特意用自定义的类存在动态分配内存进行验证
struct squareXY
{
int x;
int y;
char *m_data;
squareXY() :x(0), y(0), m_data(nullptr) {
m_data = new char[1];
*m_data = '\0';
}
squareXY(int x_, int y_, const char * other)
{
x = x_; y = y_;
m_data = new char[strlen(other) + 1];
strcpy(m_data, other);
}
//因为push_back调用拷贝构造函数,所以需要重构此构造函数
squareXY(const squareXY &oth)
{
x = oth.x; y = oth.y;
m_data = new char[strlen(oth.m_data) + 1];
strcpy(m_data, oth.m_data);
}
squareXY& operator=(const squareXY &oth)
{
if (this == &oth)return *this;
x = oth.x; y = oth.y;
delete[]m_data;
m_data = new char[strlen(oth.m_data) + 1];
strcpy(m_data, oth.m_data);
return *this;
}
~squareXY()
{
x = -1, y = -1;
if (m_data)
delete[]m_data;
}
};
Vector.hpp:
#ifndef MYVECTOR_H
#define MYVECTOR_H
#include <memory>
#include <cstddef>
#include <algorithm>
using namespace std;
template <class T>
class Vector
{
public:
Vector() : elements(nullptr), first_free(nullptr), end(nullptr) {
}
void push_back(const T&);
void reserve(const size_t capa);
//调整Vector大小,使其能容纳n个元素
//如果n小于Vector当前大小,则删除多余元素
//否则,添加采用值初始化的新元素
void resize(const size_t n);
//调整Vector大小,使其能容纳n个元素
//所有新添加元素值都为t
void resize(const size_t n