目录

vector概念

vector的遍历

1、[ ]的重载

2、迭代器

3、范围for

vector的模拟实现

成员变量

reserve函数与拷贝构造

增删函数

push_back

pop_back

迭代器

运算符重载

赋值运算符

[ ]运算符

其他函数


vector概念

1、vector是表示可变大小数组的序列容器。

2、就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

3、本质讲,vector使用动态分配数组来存储它的元素。

4、vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

vector的遍历

vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);

1、[ ]的重载

for (size_t i = 0; i < v.size(); i++) { 	cout << v[i] << " "; }

2、迭代器

vector<int>::iterator it = v.begin(); while (it != v.end()) { 	cout << *it << " "; 	it++; } cout << endl;

3、范围for

for (auto& e : v) 	cout << e; cout << endl;

vector是一个类模板,参考stl3.0的写法

成员变量

库里面的写法

 这里的iterator是被typdef了一下

所以他的类型是 T*。传入int 就为int*,传入string就为string*。

start用来标注数组的起点,finish用来标注数组有效长度的尾部,endofstorage标注数组的尾部。

所以基本上的框架就是下面这样

template<class T> class myvector { public:     typedef T* iterator;     //--------构造函数---------     myvector() 	    :_start(nullptr) 	    ,_finish(nullptr) 	    ,_endofstorage(nullptr)     {}     ~myvector()     { 	    delete[] _start; 	    _start = nullptr; 	    _finish = nullptr; 	    _endofstorage = nullptr;     }  private: 	iterator _start; 	iterator _finish; 	iterator _endofstorage; };

reserve函数与拷贝构造

先谈谈reserve函数,因为插入元素首先是增容问题,自我感觉也是这个类的核心。

先看一下下面的代码

void reserve(size_t cap) { 	if (cap > capacity()) 	{ 		size_t len = size(); 		T* tmp = new T[cap]; 		if (_start)//防止为空的时候增容 		{ 			memcpy(tmp, _start, len * sizeof(T));//拷贝 			delete[] _start;//释放原来的空间 		} 		_start = tmp; 		_finish = _start + len; 		_endofstorage = _start + cap; 	} }

当大于实际容量时,才增容,否则不增容。增容的逻辑就是开辟一块新容量的空间,将之前的内容拷贝过来(如果没有之前相等),然后更改对应的三个指针。

上面的代码表面看着没什么问题,其实存在一个很严重的bug,那就是浅拷贝。

memcpy 将_start内容拷贝到tmp里面,如果是基本类型的数据,还不会出bug,如果是自定义类型,就有可能会出错。例如string类型,string类型里面有一个char*类型的指针,该指针指向了一块堆上的空间,如果只是单独的把_start的内容拷贝给tmp中,则一旦释放掉_start,会调用string的析构函数,则tmp里面的内容都被析构了,代码会崩溃。

正确的方法

void reserve(size_t cap) { 	if (cap > capacity()) 	{ 		size_t len = size(); 		T* tmp = new T[cap]; 		if (_start) 		{ 			for (size_t i = 0; i < len; i++) 			{ 				tmp[i] = _start[i];//调用类型T自带的赋值完成深拷贝 			} 			delete[] _start; 		} 		_start = tmp; 		_finish = _start + len; 		_endofstorage = _start + cap; 	}

拷贝构造

myvector(const myvector<T>& v)//深拷贝     :_start(nullptr)     ,_finish(nullptr)     ,_endofstorage(nullptr) { 	reserve(v.capacity()); 	for (size_t i = 0; i < v.size(); i++) 	{ 		*_finish = v[i]; 		_finish++; 	} }

增删函数

push_back

尾插,如果_finish == endofstorage,则需要增容,注意刚开始为为空时的情况。

void push_back(const T& x) { 	if (_finish == _endofstorage) 	{ 		size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2; 		reserve(newcapacity); 	} 	*_finish = x; 	_finish++; }

pop_back

尾删,在入口处判断是否合法,即_start<_finish。

void pop_back() { 	assert(_start < _finish);//首先得判断是否为空数组 	_finish--; }

迭代器

vector的迭代器也比较简单,和string的类似。

iterator begin() { 	return _start; } iterator end() { 	return _finish; } const_iterator begin() const//const迭代器 typedef const T* const_iterator; { 	return _start; } const_iterator end() const { 	return _finish; }

运算符重载

赋值运算符

const myvector<T>& operator=(const myvector<T>& v) { 	delete[] _start; 	_start = nullptr; 	_finish = nullptr; 	_endofstorage = nullptr;//先清除之前的内容,然后记得置空,不然重新开辟空间会出错 	reserve(v.capacity()); 	for (size_t i = 0; i < v.size(); i++) 	{ 		*_finish = v[i]; 		_finish++; 	} 	return *this; }

现代写法思路一样,用swap函数,利用临时对象的特性,交换空间

void swap(myvector<T>& v) { 	std::swap(_start, v._start); 	std::swap(_finish, v._finish); 	std::swap(_endofstorage, v._endofstorage); }  myvector<T>& operator=(myvector<T> v) { 	swap(v); 	return *this; }

[ ]运算符

T& operator[](size_t i) { 	assert(i < size()); 	return _start[i]; } const T& operator[](size_t i)const { 	assert(i < size()); 	return _start[i]; }

其他函数

size_t size()const//获取大小 { 	return _finish - _start; } size_t capacity()const//获取容量 { 	return _endofstorage - _start; } void resize(size_t n, const T& val = T())//修改size的大小,分情况 { 	if (n < size()) 	{ 		_finish -= size()-n; 	} 	else  	{	 		if (n > capacity()) 		{ 			reserve(n); 		} 		size_t tmp = n - size(); 		while (tmp) 		{ 			*_finish = val; 			_finish++; 			tmp--; 		} 	} }

热门文章

2月23日更新20.3M/S,2025年最新高速V2ray/SSR/Clash/Shadowrocket订阅链接免费节点地址分享

这一次的节点更新覆盖了日本、加拿大、新加坡、韩国、欧洲、香港、美国等地区,最高速度可达20.3 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

公务员国考报名时间2022具体时间(公务员国考报名时间2022年几月)

摘要: 本篇文章给大家谈谈公务员国考报名时间2022具体时间,以及公务员国考报名时间2022年几月对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录一览:1、2022国考什..

2月18日更新19.2M/S,2025年最新高速V2ray/Shadowrocket/Clash/SSR订阅链接免费节点地址分享

这一次的节点更新覆盖了韩国、香港、美国、日本、加拿大、欧洲、新加坡等地区,最高速度可达19.2 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

和田宠物医院污水处理方案(宠物医院污水处理方式)

摘要: 今天给各位分享和田宠物医院污水处理方案的知识,其中也会对宠物医院污水处理方式进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录一览:1、医院污水处理操.

1月15日更新18.4M/S,2025年最新高速Shadowrocket/Clash/V2ray/SSR订阅链接免费节点地址分享

这一次的节点更新覆盖了美国、香港、加拿大、新加坡、欧洲、日本、韩国等地区,最高速度可达18.4 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

宠爱国际动物医院电话(宠爱国际动物诊疗中心)

摘要: 本篇文章给大家谈谈宠爱国际动物医院电话,以及宠爱国际动物诊疗中心对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。本文目录一览:1、石家庄的宠物医院哪一家比较好?...

1月24日更新20.1M/S,2025年最新高速V2ray/SSR/Clash/Shadowrocket订阅链接免费节点地址分享

这一次的节点更新覆盖了欧洲、加拿大、美国、新加坡、韩国、香港、日本等地区,最高速度可达20.1 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

动物疫苗间隔多久打一次(动物疫苗打几次)

摘要: 今天给各位分享动物疫苗间隔多久打一次的知识,其中也会对动物疫苗打几次进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录一览:1、狗狗要隔多久打一次疫苗.

1月7日更新23M/S,2025年最新高速SSR/V2ray/Clash/Shadowrocket订阅链接免费节点地址分享

这一次的节点更新覆盖了日本、新加坡、加拿大、韩国、欧洲、香港、美国等地区,最高速度可达23 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

2月7日更新22.2M/S,2025年最新高速Clash/Shadowrocket/SSR/V2ray订阅链接免费节点地址分享

这一次的节点更新覆盖了香港、新加坡、日本、加拿大、韩国、美国、欧洲等地区,最高速度可达22.2 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。

归纳