c++学习笔记-----vector

一、vector的介绍及使用

(一)什么是vector?
vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确。它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
c++学习笔记-----vector_第1张图片
它的底层是由双端队列数据结构实现的。其内部成员实际上是start、finish和endofstorage三个指针构成,起始指针为start,而finish指向最后一个数据,也就是size大小就为finish-start,endofstorage是指向空间的最后一位,也就是capacity大小就为endofstorage-start;
(二)vector常用接口及实现

1.构造函数、拷贝构造和析构函数。
c++学习笔记-----vector_第2张图片

			//vector构造函数
			vector()
				:_start(nullptr)
				,_finish(nullptr)
				,_endofstoage(nullptr)
			{}
			//拷贝构造
			//比如要开名为v的5个1的空间则定义为vector v(5,1);
			vector(int n, const T& value = T())
				:_start(nullptr)
				, _finish(nullptr)
				, _endofstoage(nullptr)
			{
				reserve(n);
				while (n--)
				{
					push_back(value);
				}
			}

			template<class InputIterator>
			//拷贝构造函数:传入原vector类型的_fist和_finish;
			//比如要开一个V2,和V1一样大小的空间,则v2(v1.begin(),v1.end());
			vector(InputIterator first, InputIterator last)
				:_start(nullptr)
				, _finish(nullptr)
				, _endofstoage(nullptr)
			{
				reserve(last - first);
				while (first != last)
				{
					push_back(*first);
					first++;
				}
			}
			//v2(v1);
			vector(const vector<T>& v)
				:_start(nullptr)
				, _finish(nullptr)
				, _endofstoage(nullptr)
			{
				vector<T> temp(v.begin(), v.end());
				swap(temp);
			}
			//析构函数
			~vector()
			{
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
			

2.求空间大小类接口
c++学习笔记-----vector_第3张图片

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

			size_t capacity() const
			{
				return _endofstoage - _start;
			}
			
			void reserve(size_t n)
			{
				if (n > capacity())
				{
					size_t sz = size();
					T* temp = new T[n];
					if (_start)
					{
						for (size_t i = 0; i < sz; ++i)
						{
							temp[i] = _start[i];
						}
					}
					_start = temp;
					_finish = _start + sz;
					_endofstoage = _start + n;
				}
			}

			void resize(size_t n, const T& value = T())
			{
				if (n > capacity())
				{
					reserve(n);
				}
				if (n < size())
				{
					_finish = _start + n;
				}
				else
				{
					while (_finish != _start + n)
					{
						*_finish = value;
						++_finish;
					}
				}
			}

3.vector 增删查改
c++学习笔记-----vector_第4张图片

void check_capacity()
			{
				if (_finish == _endofstoage)
				{
					size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
					reserve(newcapacity);
				}
			}

			void push_back(const T& x)
			{
				check_capacity();
				*_finish = x;
				++_finish;
			}

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

			void swap(vector<T>& v)
			{
				std::swap( v._start);
				std::swap(v._finish);
				std::swap(v._endofstorage);
			}

			iterator insert(iterator pos, const T& x)
			{
				assert(pos <= _finish&&pos >= _start)
				size_t oldpos = pos - _start;
				check_capacity();
				pos = _start + oldpos;
				T* end = _finish-1;
				while (end >= pos)
				{
					*(end + 1) = *end;
					--end;
				}
				*pos = x;
				++_finish;
				return pos;
			}

			iterator erase(Iterator pos)
			{
				assert(pos <= _finish&&pos >= _start)
				iterator it = pos + 1;
				while (it != _finish)
				{
					*(it - 1) = *it;
				}
				--_finish;
				return pos;
			}
			T& operator[](size_t pos)
			{
				assert(pos < size());
				return _start[pos];
			}

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

4.vector iterator(迭代器) 的使用
c++学习笔记-----vector_第5张图片

typedef T* iterator;

			typedef const T* const_iterator;

			iterator begin()
			{
				return _start;
			}

			iterator end()
			{
				return _finish;
			}

			const_iterator cbegin() const
			{
				return _start;
			}

			const_iterator cend() const
			{
				return _finish;
			}

二、vector深度剖析

1.迭代器失效问题

vector的插入操作如果导致底层空间重新开辟,则迭代器就会失效,但容量多余的前提下插入数据,迭代器不失效。
vector删除,当前元素肯定失效,后面元素会牵扯到移动数据,因此删除元素后面的迭代器也会失效

2.使用memcpy拷贝问题
当我们模拟vector中reserve函数时,使用memcpy进行的拷贝时,如果vector定义的是自定义类型,它实际上是浅拷贝。就会造成崩溃。

void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				memcpy(tmp, _start, sizeof(T)*size());
				delete[] _start;
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}
  1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中。
  2. 如果拷贝的是自定义类型的元素,memcpy即高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

你可能感兴趣的:(c++学习笔记,c++)