C++【STL容器系列(二)】vector的模拟实现

1. vector的结构

我们通过查看vector的底层,能发现结构并不是我们所想的数组,_size,_capacity
在这里插入图片描述
而是由三个指针所组成的,这三个指针分别为;start:开始元素finish:末尾元素的后一个位置end_of_storage:容量(iterator是在前面typedef过的,原型为 T*)

我们前面讲结构,vector是通过模板来实现的,但模板并不能分离成两个文件,所以本次模拟只会有"vector.h"这个头文件。

由于我们是模拟实现,那么底层结构也要是三个指针

template<class T>
class vector
{
   
public:
	typedef T* iterator;
private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

2. vector的默认成员函数

2.1构造函数

		vector(); //默认构造
		template <class InputIterator>
		vector(InputIterator first, InputIterator last) //迭代器构造
		vector(size_t n, const T& x = T()) //用n个val初始化构造

2.1.1 默认构造

其实默认构造我们并不需要写,因为我们在声明成员变量的时候就已经给了缺省值nullptr,所以写不写都无所谓,用编译器生成的默认构造就可以了,但是如果你写了一个构造函数,那么编译器就不会生成默认构造,这时候就可以使用C++11引入的default,来让编译器生成默认构造。

vector() = default; //让编译器生成默认构造

2.1.2 迭代器构造

这里其实并不复杂,push_back迭代器所代表的内容就好了。

但问题是:为什么要在多写一个模板出来呢?

答案也很简单,因为外面的模板和这个模板推导的类型不一样,外面是推导vector<T>中的T,这个是推导整个vector<T>

拿vector<int>举例,外面模板类型是 int,里面模板类型是vector<int>

		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
   

			while (first != last)
			{
   
				push_back(*first);
				++first;
			}
		}

2.1.3 用n个val初始化构造

这个也很简单,用一个循环来push_back(val)就好了

		vector(size_t n, const T& x = T())
		{
   
			reserve(n); 
			for (size_t i = 0; i < n; ++i)
			{
   
				push_back(x);
			}
		}
  • reserve: 用于提前开好空间,这样就不用反复扩容了

但是这样写会有问题,我使用其他类型不会报错,但是使用vector<int>(n,val)的时候就会报错!!!
在这里插入图片描述
竟然调用了迭代器初始化的构造函数,这是为什么呢,原因就在模板这里。

调用函数的机制是只要类型匹配,怎么简单怎么来,由于用n个val初始化是模板参数(const T& x = T()),迭代器构造也是模板参数,但是用n个val初始化还有一个 size_t 的参数,那么模板推导后有需要类型转换,势必会麻烦一点,而迭代器是两个模板参数,推导完可以直接使用,所以编译器在调用函数的时候,自然而然就会调用迭代器版本的构造。

解决方法也很简单,就是自己再写一个 int 版本的构造(其实库里也是这样实现的)
在这里插入图片描述

所以我们实现的时候,要多实现一个整形版本的构造(这里只实现了int版本的)

		vector(size_t n, const T& x = T(
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值