当前位置: 首页 > news >正文

vector的使用和模拟

vector的基本使用

构造函数:

template<class Constain>
void Print(const Constain& con)
{for (auto& e : con){cout << e << ' ';}cout << endl;
}int main()
{//以下三种都可以一般会忽略括号,直接用花括号//vector<int> v1({ 1,2,3,4,5 });vector<int> v1{ 1,2,3,4,5 };//vector<int> v1 = { 1,2,3,4,5 };Print(v1);vector<int> v2(20, 100);Print(v2);vector<int> v3(v1.begin() + 2, v1.end());Print(v3);return 0;
}

运行结果:

以上是我觉得较为有用的初始化构造函数(c++98)需要其他构造可以直接查阅文档vector::vector - C++ Reference

拷贝构造:

	vector<int> v4 = v1;//这里继承了上面的代码,{1,2,3,4,5}Print(v4);

迭代器:

这里迭代器就不一一写了,这里可以理解成像指针一样的东西,进行遍历使用就好了,如:

//可修改
void test02()
{vector<int> v1 = {1,2,3,4,5};vector<int>::iterator it1 = v1.begin();while (it1 != v1.end()){cout << *it1 << ' ';++it1;}
}//只读
void test03()
{vector<int> v1 = {1,2,3,4,5};vector<int>::const_iterator it1 = v1.cbegin();while (it1 != v1.cend()){cout << *it1 << ' ';++it1;}
}//反向迭代器
void test04()
{vector<int> v1 = {1,2,3,4,5};vector<int>::reverse_iterator it1 = v1.rbegin();while (it1 != v1.rend()){cout << *it1 << ' ';++it1;}
}

运行结果:

容器:

void test05()
{vector<string> v1 = { "hellow","world","!!!!!" };cout << "大小:" << v1.size() << endl;cout << "扩容前:" << v1.capacity() << endl;cout << v1.max_size() << endl;//没实际意义(扩容阔不了这么大)v1.resize(5, "bear");Print(v1);cout << "resize扩容后:" << v1.capacity() << endl;cout << "判空:" << v1.empty() << endl;v1.reserve(10);cout <<"reserve扩容后:" << v1.capacity() << endl;v1.shrink_to_fit();cout << "shrink_to_fit缩容后:" << v1.capacity() << endl;
}

 元素访问:

void test06()
{vector<string> v1 = { "hellow","world","!!!!!" };cout << "operator[]:" << v1[1] << endl;cout <<"at:" << v1.at(1) << endl;cout << "front:" << v1.front() << endl;cout << "back:" << v1.back() << endl;cout << "data:" << v1.data() << endl;//返回起始元素地址}                                                              

运行结果:

修改:

void test07()
{vector<int> v1{1,2,3,4,5};v1.assign(20, 100);//替代原来的vectorPrint(v1);vector<int> v2;v2.push_back(1);v2.push_back(2);v2.push_back(3);v2.push_back(4);v2.push_back(5);Print(v2);v2.pop_back();cout << "pop_back后:";Print(v2);v2.insert(v2.begin()+2, 100);cout << "insert插入后:";Print(v2);v2.erase(v2.begin() + 1);cout << "erase删除后:";Print(v2);vector<int> v3;v3.swap(v2);cout << "交换后的v2:";Print(v2);cout << "交换后的v3:";Print(v3);v3.clear();cout << "clear的v3:";Print(v3);
}

emplace_back和push_back区别

emplace_back和push_back(构造一个临时对象,然后将其拷贝或移动到容器中)初始化时,在特殊场景下emplace_back效率会更高(直接在容器内存中构造对象,避免创建临时对象push_back和emplace_back在扩容过程中都会调用拷贝构造

void test08()
{struct A{A(int a,int b,int c):_a(a),_b(b),_c(c){ cout << "A()" << endl;}A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;_b = aa._b;_c = aa._c;}int _a = 1;int _b = 2;int _c = 3;};vector<int> v1;//内置类型效率差不多v1.push_back(1);v1.emplace_back(1);for (auto& e : v1){cout << e << " ";}cout << endl;cout << endl;vector<A> v2;//v2.reserve(10);//完整对象A aa1(4, 5, 6);cout << "********************************" << endl;cout << "push_back完整实例化对象:"<<endl;v2.push_back(aa1);v2.push_back(A(7,8,9));//匿名对象cout << "push_back:传递构造参数(不是完整实例化对象)" << endl;//需要调用构造,再调用拷贝构造v2.push_back({ 1,2,3 });cout << "emplace_back完整实例化对象:"<<endl;;//这里拷贝2次是因为第一个拷贝是因为扩容拷贝,然后第二次是需要拷贝到vector中v2.emplace_back(aa1);v2.emplace_back(A(7, 8, 9));cout << "emplace_back:传递构造参数(不是完整实例化对象)" << endl;//避免临时对象的产生,直接调用构造(效率较高)v2.emplace_back( 1,2,3 );cout << endl;cout << endl;}

这里很明显在传递构造参数时,就会使得拷贝构造变少(甚至不拷贝),但是在其他方面如已初始化的反而会拷贝更多拷贝;

结构化绑定

结构化绑定(用于类型是自定义类型的类,就是一个自定义类型有多个成员访问就好用,和范围for一样,只不过范围for不好写多个成员访问,这里结构化绑定就是可以直接访问)。可能发生拷贝构造,可以用引用消除这个拷贝构造

void test09()
{struct A{A(int a, int b, int c):_a(a), _b(b), _c(c){cout << "A()" << endl;}A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;_b = aa._b;_c = aa._c;}int _a = 1;int _b = 2;int _c = 3;};//c++17标准//auto [x, y, z] = A(2, 3, 4);A aa1(2, 3, 4);vector<A> v4;v4.push_back(aa1);for (auto [x, y, z] : v4){cout << x << ' ' << y << ' ' << z << endl;}
}

迭代器失效

vector迭代器失效,指的是不能继续使用迭代器(扩容会改变迭代器指针是位置,而对应的pos位置指针不会给你改变,会导致野指针)对于迭代器失效,就可以使用返回值来保留当前位置(更新就能继续使用)

vector的模拟

迭代器:

namespace bear
{template<class T>class vector{public:// Vector的迭代器是一个原生指针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;}private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾};
}

容器:

        //sizesize_t size() const{return _finish - _start;}//capacitysize_t capacity() const{return _endOfStorage - _start;}//扩容void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t old_size = _finish - _start;if (_start){//memcpy(tmp, _start,_finish-_start);//只能浅拷贝for (size_t i = 0; i < size(); i++){//可以调用需要深拷贝的构造tmp[i] = _start[i];}delete[] _start;}_start = T;_finish = _start + old_size;_endOfStorage = _start + n;}}//resizevoid resize(size_t n, const T& value = T()){if (n > capacity()){reserve(n);iterator it1 = _start + size();while (it1 != _start + n){(*it1) = value;++it1;}_finish = _start + n;}else{_finish = _start + n;}}

元素访问:

        ///////////////access/////////////////////////////////下标引用T& operator[](size_t pos){assert(pos <= _finish);return _start[pos];}const T& operator[](size_t pos)const{assert(pos <= _finish);return _start[pos];}

元素修改:

        ///////////////modify/////////////////////////////void push_back(const T& x){//空间不够if (_finish == _endOfStorage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;++_finish;}void pop_back(){--_finish;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._start);std::swap(_endOfStorage, v._endOfStorage);}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _endOfStorage){//保存pos相对位置(这里也是为了防止迭代器失效)size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = len + _start;}iterator it = _finish - 1;while (it >= pos){*(it + 1) = *it;--it;}*_finish = x;++_finish;//防止迭代器失效return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);iterator it = pos+1;while (it != _finish){*(it - 1) = *it;++it;}--_finish;return pos;//防止迭代器失效}

构造、赋值和析构:

        // construct and destroyvector():_start(nullptr),_finish(nullptr),_endOfStorage(nullptr){}vector(int n, const T& value = T()){resize(n, value);}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(first);++first;}}//拷贝vector(const vector<T>& v){reserve(v.capacity());for (auto e : v){push_back(e);}}//赋值vector<T>& operator= (vector<T> v){swap(v);return *this;}//析构~vector(){delete[] _start;_start = _finish = _endOfStorage = nullptr;}

总代码综合:

#pragma once#include<iostream>
#include<assert.h>
namespace bear
{template<class T>class vector{public:// Vector的迭代器是一个原生指针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;}// construct and destroyvector():_start(nullptr),_finish(nullptr),_endOfStorage(nullptr){}vector(int n, const T& value = T()){resize(n, value);}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(first);++first;}}//拷贝vector(const vector<T>& v){reserve(v.capacity());for (auto e : v){push_back(e);}}//赋值vector<T>& operator= (vector<T> v){swap(v);return *this;}//析构~vector(){delete[] _start;_start = _finish = _endOfStorage = nullptr;}//sizesize_t size() const{return _finish - _start;}//capacitysize_t capacity() const{return _endOfStorage - _start;}//扩容void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t old_size = _finish - _start;if (_start){//memcpy(tmp, _start,_finish-_start);//只能浅拷贝for (size_t i = 0; i < size(); i++){//可以调用需要深拷贝的构造tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + old_size;_endOfStorage = _start + n;}}//resizevoid resize(size_t n, const T& value = T()){if (n > capacity()){reserve(n);iterator it1 = _start + size();while (it1 != _start + n){(*it1) = value;++it1;}_finish = _start + n;}else{_finish = _start + n;}}///////////////access/////////////////////////////////下标引用T& operator[](size_t pos){assert(pos <= _finish);return _start[pos];}const T& operator[](size_t pos)const{assert(pos <= _finish);return _start[pos];}///////////////modify/////////////////////////////void push_back(const T& x){//空间不够if (_finish == _endOfStorage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;++_finish;}void pop_back(){--_finish;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._start);std::swap(_endOfStorage, v._endOfStorage);}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _endOfStorage){//保存pos相对位置(这里也是为了防止迭代器失效)size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = len + _start;}iterator it = _finish - 1;while (it >= pos){*(it + 1) = *it;--it;}*_finish = x;++_finish;//防止迭代器失效return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos <= _finish);iterator it = pos+1;while (it != _finish){*(it - 1) = *it;++it;}--_finish;return pos;//防止迭代器失效}private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾};
}

总结:

vector这里较为重要的有vector的使用和vector的模拟,其中迭代器的失效很重要,通过底层实现vector的中发现在任意删和任意插(insert,erase)中pos指向会发生改变,这就导致了迭代器的失效,这里解决这个问题就是更新pos位置,然后返回pos对应的指针。

http://www.dtcms.com/a/399679.html

相关文章:

  • 织梦网站栏目无法生成网站关键字多少个
  • n8n中的postgres节点中插入数据怎么自动插入,不设置id?
  • 全钢PVC防静电地板优势与不足全解析
  • 上海魔力网站建设公司免费制作链接的软件
  • 巅云建站企业购物平台
  • UMI企业智脑:数字资产与知识管理的行业新标杆
  • 北京 旅游攻略 颐和园 圆明园(第一天下午逛) 长城最后一天早上逛 如果到北京早 也可以第一天长城
  • 孝感做网站如何做网站视频模板
  • 网站开发成本有哪些idea 做网站登录
  • 网站推广在哪好外贸网站备案不成功的原因有哪些
  • 可以做锚文本链接的网站网站做下载wordpress
  • 创新型的网站建设wordpress滑动验证码
  • elasticsearch更换为opensearch
  • 微服务和大数据在架构上的相似之处
  • 专业优化网站建设襄城县城乡建设管理局网站
  • 电子商务网站设计的基本要求如何查看网站跳出率
  • 用vio_uart_rpc协议,测试IIC接口的AT24C64
  • 杭州网站快速备案正规电商培训班
  • 台州做网站多少钱镇江佳鑫网络科技有限公司
  • APM v4.1.1 | 免费音乐听歌B站油管音乐播放器
  • 牛客算法基础noob51 杨辉三角
  • SVN忽略文件不生效
  • MyBatis开启自动下划线转驼峰
  • 自己做网站 搜索功能开发汽车商城网站模板免费下载
  • 加拿大住宅代理指南(2025年更新)
  • 专门建站的公司制作u盘启动盘
  • redis的set集合的常规使用
  • 【C++模板编程】从泛型思想到实战应用
  • auto 关键字
  • 工程项目建设自学网站哪家网站开发好