从C++开始的编程生活(12)——vector简单介绍和迭代器
前言
本系列文章承接C语言的学习,需要有C语言的基础才能学会哦~
第12篇主要讲的是有关于C++的vector简单介绍和迭代器失效。
C++才起步,都很简单!!
目录
前言
vector
基本接口
assign赋值
insert插入
ps:
vector底层实现
迭代器失效
vector
是C++的顺序容器,也就是顺序表,是模板,需要模板参数。
vector的构造,析构等基本接口与string用法基本相同,这里不加赘述,
基本接口
assign赋值
v1.assign( {10,20,30} );
覆盖原本内容,若超出容量会扩容。
insert插入
v1.insert(v1.begin(), 9);
vector的插入不支持直接靠下标插入,需要通过指针加减指向插入位置。
ps:
vector扩容在vs下以1.5倍扩容。
其他接口功能、迭代器等与string相似性很高,了解string的用法即可举一反三到vector中使用。
String参考文章《--------点击学习
vector底层实现
#pragma once
#include<assert.h>
namespace bit
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){ }vector(initializer _list<T> il):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){ reserve(li.size());for (auto e : li){push_back(e);}}template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}vector(int n, const T& val = T()){reserve(n);for (int i = 0; i < n; i++){push_back(val);}}vector(initializer _list<T> il){reserve(il.size());for (auto& e : li){push_back(e);}}vector(const vector<T>& v){reserve(v.capacity());for (auto& e : v){push_back(e);}}void swap(vector<T>& tmp){std::swap(_start, tmp._start);std::swap(_finish, tmp._finish);std::swap(_endofstorage, tmp._endofstroage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}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, T val = T()){if (n > capacity()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}}void reserve(size_t n){if (n > capacity()){size_t oldSize = size();T* tmp = new T[n];if (_start){//memcpy(tmp, _start, sizeof(T) * oldSize);for (size_t i = 0; i < oldSize; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + oldSize;_endofstorage = _start + n;}}void push_back(const T& x){if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*finish = x;++_finish;}bool empty(){return _start == _finish;}void pop_back(){assert(!empty());--_finish;}iterator insert(iterator pos, const T& x){assert(pos >= _start && pos < _finish);if (_finish == _endofstorage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;}iterator i = _finish - 1;while (i >= pos){*(i + 1) = *i;--i;}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator i = pos + 1;while (i < _finish){*(i - 1) = *i;++i;}_finish--;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};
}
迭代器失效
①扩容或者缩容后,数据存放位置可能改变了,导致函数内部的迭代器变成了野指针。
②删除数据之后,发生了数据的挪动,但是存放位置没变,迭代器虽然有可能不会变为野指针,但是不再指向原来的数据,可能会导致逻辑问题,也认为是发生了迭代器失效。
vs对迭代器失效的检验更加严格,以上两种情况发生都会导致报错,不让你访问失效迭代器。Linus对第②种情况可能不会报错崩溃。
失效的迭代器需要更新之后才能访问!!(赋新的、正确的值)
❤~~本文完结!!感谢观看!!接下来更精彩!!欢迎来我博客做客~~❤
