文章目录
容器(container)
容器是用来存储数据的,数据可以是用户自定义类型(对象),也可以是内置类型。
容器的分类
-
顺序容器 vector(向量容器) deque(双端队列容器) list(双向链表)
-
关联容器 set(单重集合) multiset(双重集合) map(单重映射表) multimap(多重映射表)
-
容器适配器 stack(栈) queue(队列) prority_queue(优先级队列)
向量容器(vector)
定义:向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)
简单的认为,向量是一个能够存放任意类型的动态数组。
特点:
-
在内存中是一片连续的存储区域,初始化的时候,可以指定容量,比如如果定义容量50 的容器存储 60个string对象,由于初始容量不足60,容器将会重新定义一个容量是原来的2倍新容器,然后构造原容器的对象到新容器,再把原容器的对象进行析构。
-
读取速度快,插入删除效率低.如果仅仅在容器头或尾部进行增删改,推荐使用deque,专门提供了对首尾的操作。
-
容器使用一个内存分配器对象来动态地处理它的存储需求。
库中有关顺序容器的函数
1.push_back 在数组的最后添加一个数据
2.pop_back 去掉数组的最后一个数据
3. at 得到编号位置的数据
4.begin 得到数组头的指针
5.end 得到数组的最后一个单元+1的指针
6.front 得到数组头的引用
7.back 得到数组的最后一个单元的引用
8.max_size 得到vector最大可以是多大
9.capacity 当前vector分配的大小
10.size 当前使用数据的大小
11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
12.reserve 改变当前vecotr所分配空间的大小
13.erase 删除指针指向的数据项
14.clear 清空当前的vector
15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)
16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)
17.empty 判断vector是否为空
18.swap 与另一个vector交换数据
自己实现的顺序容器
容器配置器
- 将内存的开辟和对象的构造分离开
- 将内存的释放的对象的析构分离开
template<typename T>
class Allocator
{
public:
T* allocate(size_t size) // 开辟size大小的内存
{
return (T*)malloc(size);
}
void deallocate(void *ptr) // 释放内存
{
free(ptr);
}
void construct(T *ptr, const T &val) // 构造
{
new (ptr) T(val);//在已经开辟好的内存上进行构造
}
void destroy(T *ptr) // 析构
{
ptr->~T();
}
};
vector实现
template<typename T, typename allocator = Allocator<T>>
class Vector
{
public:
// 按指定size进行构造,size个空间,没有元素(只分配空间不初始化)
Vector(int size = 0)
{
if (size == 0)
{
_first._ptr = _last._ptr = _end._ptr = nullptr;//当size为0不开辟空间
}
else
{
_first._ptr = mAllocator.allocate(size * sizeof(T));
_last._ptr = _first._ptr;//没有元素
_end._ptr = _first._ptr + size;
}
}
// 按指定size进行构造,添加size个元素,元素值是val
Vector(int size, const T &val)
{
_first._ptr = mAllocator.allocate(size * sizeof(T));//先分配空间
for (int i = 0; i < size; ++i)
{
mAllocator.construct(_first._ptr+i, val);//在每一个位置上进行构造
}
_last._ptr = _end._ptr = _first._ptr + size;//对空间上的每个元素进行构造
}
// 按[first, last)区间的元素来构造Vector
Vector(T *first, T *last)
{
int size = last - f