[C++进阶篇]STL中vector的使用

一、vector的介绍

1.vector的介绍
  • vector是表示可变大小数组的序列容器。
  • vector也采用的连续存储空间来存储元素,就是可以采用下标对vector的元素进行访问,和数组一样。
  • 它的大小是可以动态改变的。

2.重要的接口组成

[C++进阶篇]STL中vector的使用_第1张图片


二、 vector迭代器的使用

2.1 vector iterator 的使用

[C++进阶篇]STL中vector的使用_第2张图片

void testvector2()   
{
	vector v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);


    vector::iterator it = v1.begin();  //普通正向迭代器可以读可以写
	while (it != v1.end())
	{
		*it = *it * 2;
		cout << *it << " ";
		it++;
	}


vector::reverse_iterator vit = v1.rbegin();  //reverse逆置  reserve保留
	while (vit != v1.rend())
	{
		cout << *vit << " ";
		vit++;
	}
	cout << endl;
	for (auto e : v1)     //编译器替换成迭代器生成的
	{
		cout << e << " ";
	}
	cout << endl;
}


void print_vector(const vector& v)  //传引用,加引用就加const,const 对象就要用const的迭代器
{
	vector::const_iterator it = v.begin();
	while (it != v.end())
	{
		//*it = *it + 1;  const的迭代器不可以写,修改
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

 

2.2 vector空间相关函数

[C++进阶篇]STL中vector的使用_第3张图片

在上一章string中我们详细介绍过所以就不去讲解了

但这里我我们要注意一下:

resize:是直接开空间resize(100)是从低一百个位置开始计算

size是100

reserve:是提前开空间,第0个位置

size是0

2.3 vector的增删查改

[C++进阶篇]STL中vector的使用_第4张图片

2.4 find,sort,swap的介绍

参数是一段迭代器区间,在此区间你要添加需要查找的值,找到后返回这个值对应的迭代器位置
若找不到,则返回迭代器last

vector vv{1,2,3,4,5,6,7,8,9};
auto pos = find(vv.begin(),vv.end(),5);
cout<<*pos;

sort函数

[C++进阶篇]STL中vector的使用_第5张图片

他本质就是快排,所以当我们输入一些数的时候,调用迭代器,他会自动排序

vector vv{5,7,3,9,6,4,1,2,8};
sort(vv.begin().vv.end());

swap函数

这里就不过多介绍了,懂得都懂


2.5  空间关系

[C++进阶篇]STL中vector的使用_第6张图片

 

三、迭代器失效问题

vector底层就是一个指针,vector的迭代器就是原生态指针T*

因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)

3.1  使用迭代器区间来构造

在顺序表中存放string类型:

string str("abcdefg");
vector vv(str.begin(),str.end());

template 
vector(InputIterator first, InputIterator last)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}

四、深浅拷贝问题


  • resize开辟有效数据空间并初始化时不能使用memset初始化,因为mem系列函数是按字节去处理
  • reserve开辟容量空间时开辟的新空间不能使用memcpy把旧空间的数据拷贝过去,要使用循环赋值过去,因为memcpy是浅拷贝,浅拷贝最后会导致释放旧空间新空间的指针指向一块已被释放的空间,造成程序崩溃

[C++进阶篇]STL中vector的使用_第7张图片

代码测试:

Vector(const Vector& v)
{
	assert(v._start && v._finish && v._endofsto);
	_start = new T[v.capacity()];//给size或capacity都可以
	memcpy(_start, v._start, sizeof(T) * v.size());
}

 解决办法:

Vector(const Vector& v)
{
	assert(v._start && v._finish && v._endofsto);
	_start = new T[v.capacity()];//给size或capacity都可以
	//memcpy(_start, v._start, sizeof(T) * v.size()); //使用memcpy时,数组是二维数组会发生问题
	for (size_t i = 0; i < size(); i++)
	{
		_start[i] = v._start[i];
		_finish = _start + v.size();
	}
	_endofsto = _start + v.capacity();
}

、二维数组的开辟和图解

song::vector vv(n); 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类型的,每行没有包含任何元素,如果n为5时如下所示

[C++进阶篇]STL中vector的使用_第8张图片


代码总结:

#pragma once
#include
#include
#include
#include

using namespace std;

template
class Vector
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;

	void swap(Vector& v)
	{
		std::swap(_start, v._start);
		std::swap(_finish, v._finish);
		std::swap(_endofsto, v._endofsto);
	}

	iterator begin()
	{
		return _start;
	}

	const_iterator begin()const
	{
		return _start;
	}

	iterator end()
	{
		return _finish;
	}

	const_iterator end()const
	{
		return _finish;
	}

	Vector()
		:_start(nullptr)
		, _finish(nullptr)
		, _endofsto(nullptr)
	{

	}

	template
	Vector(InputIterator first, InputIterator last)//有迭代器区间的构造
		:_start(nullptr)
		, _finish(nullptr)
		, _endofsto(nullptr)
	{
		while (first != last)
		{
			push_back(*first);
			first++;
		}
	}

	//这里将size_t改为int可以解决间接寻址的错误,但是库中使用的是size_t
	Vector(int n, const T& val = T())//构造函数:插入n个val,T()是匿名对象的缺省,调用默认构造函数
		:_start(nullptr)
		, _finish(nullptr)
		, _endofsto(nullptr)
	{
		reserve(n);
		for (size_t i = 0; i < n; i++)
		{
			push_back(val);
		}
	}

	~Vector()
	{
		delete[] _start;
		_start = _finish = _endofsto = nullptr;
	}

	/*Vector(const Vector& v)
		:_start(nullptr)
		,_finish(nullptr)
		,_endofsto(nullptr)
	{
		reserve(v.size());
		for (const auto& e : v)
		{
			push_back(e);
		}
	}*/

	Vector(const Vector& v)
	{
		assert(v._start && v._finish && v._endofsto);
		_start = new T[v.capacity()];//给size或capacity都可以
		memcpy(_start, v._start, sizeof(T) * v.size()); //使用memcpy时,数组是二维数组会发生问题
		/*for (size_t i = 0; i < size(); i++)
		{
			_start[i] = v._start[i];
			_finish = _start + v.size();
		}
		_endofsto = _start + v.capacity();*/
	}

	size_t capacity()const
	{
		return _endofsto - _start;
	}

	size_t size()const
	{
		return _finish - _start;
	}

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

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

	//void reserve(size_t n)
	//{
	//	if (n > capacity())
	//	{
	//		size_t sz = size();
	//		T* tmp = new T[n];
	//		if (_start)
	//		{
	//			memcpy(tmp, _start, sizeof(T) * size());
	//			delete[] _start;
	//		}
	//		_start = tmp;
	//		_finish = _start + sz;
	//		_endofsto = _start + n;//开辟n个空间
	//	}
	//}

	void reserve(size_t n)
	{
		if (n > capacity())
		{
			size_t sz = size();
			T* tmp = new T[n];
			if (_start)
			{
				memcpy(tmp, _start, sizeof(T)*sz);
				/*for (size_t i = 0; i < sz; ++i)
				{
					tmp[i] = _start[i];
				}
				delete[] _start;*/
			}

			_start = tmp;
			_finish = _start + sz;
			_endofsto = _start + n;
		}
	}


	void resize(size_t n, const T& val = T())
	{
		if (n > capacity())//扩容
		{
			reserve(n);
		}
		if (n > size())//初始化,前面的数据不动,后面添加val
		{
			while (_finish < _start + n)
			{
				*_finish = val;
				_finish++;
			}
		}
		else if (n <= size())//删除数据,但不改变原先的数据
		{
			_finish = _start + n;
		}
	}

	void push_back(const T& x)
	{
		/*if (_endofsto == _finish)
		{
			reserve(capacity() == 0 ? 4 : 2 * capacity());
		}
		*_finish = x;
		_finish++;*/
		insert(end(), x);
	}

	void pop_back()
	{
		assert(_finish > _start);
		_finish--;
	}

	iterator insert(iterator pos, const T& x)//若不传入地址或引用,发生扩容后,p位置将不在start和finish之间                               
	{                                    //虽然在函数内部修改了pos,但是pos只是p的一份拷贝
		assert(pos >= _start && pos <= _finish); //库中没有传地址或引用,按照库中的来
		if (_finish == _endofsto)
		{
			size_t len = pos - _start;
			reserve(capacity() == 0 ? 4 : 2 * capacity());
			pos = _start + len;//不更新pos位置的话,扩容后,迭代器会失效
		}
		iterator end = _finish - 1;
		while (end >= pos)
		{
			*(end + 1) = *end;
			end--;
		}
		*pos = x;
		_finish++;
		return pos;
	}

	iterator erase(iterator pos)
	{
		assert(pos >= _start && pos < _finish);
		iterator end = pos;
		while (end <= _finish)
		{
			*(end) = *(end + 1);
			end++;
		}
		_finish--;
		return pos;

		//if (size() < capacity() / 2)//库中可能是这样实现的,缩容可能会有迭代器失效的问题
		//{
		//	//缩容
		//}
	}

	Vector& operator=(Vector v)//要交换this和v就不能传引用
	{
		swap(v);//交换后,局部变量v销毁时刚好把*this原先的空间给释放掉了
		return *this;
	}

	T& front()
	{
		assert(size() > 0);
		return *_start;
	}
	T& back()
	{
		assert(size() > 0);
		return *_finish;
	}

private:
	iterator _start;
	iterator _finish;
	iterator _endofsto;
};

以上就是今天的vector实现,喜欢的话请留下您的支持吧,感谢您的收看



 

你可能感兴趣的:(c++,c++,开发语言)