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

C++学习之STL学习:vector类的使用

         之前我们了解到了string类的使用并通过对string常用接口的模拟实现对其底层有更深刻的了解。接下来我们将进一步深入学习STL类的下一个区:vector

        vector在某些方面类似于顺序表的功能

        作者的gitee主页在这里,感兴趣的可以自行查看:楼田莉子 (riko-lou-tian) - Gitee.com

目录

vector类的初始

        vector的构造

​编辑

        初始化列表形态初始化 

     vector的析构

        vector的赋值重载

vector的迭代器

正向迭代器

反向迭代器 

const正向迭代器

const反向迭代器

vector的遍历方式

        operator[]

        at

        front​编辑

        back

        data

vector的容器操作

        size

        max_size

      capacity  

        empty

        resize

        reserve

        shrink_to_fit

vector与string的区别

vector增删查改

        push_back

        pop_back

        find

        insert

​编辑         erase

        swap

        clear ​编辑

        emplace​编辑

 emplace_back                   

        更好的遍历方式:结构化绑定

assign  

vector的非成员函数重载

        vector的关系运算符重载

​编辑         swap函数

内存池函数 

模板专用化 

         成员类:引用

        成员函数:

        flip

        swap 

        类模板特化 

一些题目:

        杨辉三角

      只出现一次的数字1


vector类的初始

       官方文档:

        vector::begin - C++ 参考

        std::vector - cppreference.com

        使用vector类之前必须包含头文件<vector>和

using namespace std

        vector的构造

构造函数接口功能说明
vector()(重点)无参构造
vector(size_type n,const value_type&val=value_type())构造并初始化n个val
vector(const vector& x)(重点)拷贝构造
vector(Inputlterator first,Inputlterator last)使用迭代器进行初始化构造

void test1()
{//无参数构造vector<int> v1;//v1的尾插元素v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);//有参数构造vector<int> v2(5, 0);//初始化了5个值为0的元素//利用迭代器区间初始化vector<int>v3(v1.begin(), v1.end());
}

        初始化列表形态初始化 

//初始化列表初始化
vector<int>v1{ 1,2,3,4,5,6,7,8,9,10 };
vector<int>v2 = { 1,2,3,4,5,6,7,8,9,10 };
vector<int>v3({1,2,3,4,5,6,7,8,9,10});

     vector的析构

        vector的赋值重载

vector的迭代器

迭代器使用接口说明
begin+end(重点)获取第一个数据位置的迭代器或者const迭代器,获取最后一个数据的下一个位置的迭代器
rbegin+rend获取最后一个数据位置的逆置迭代器或者const逆置迭代器,获取第一个数据前一个位置上的逆置迭代器

        同string一样,vector 也有四组共8个迭代器。

正向迭代器

反向迭代器 

const正向迭代器

const反向迭代器

vector的遍历方式

vector的遍历方式功能
operator[]返回对容器中位置n处元素的引用
at返回对容器中位置n处元素的引用
front返回第一个元素的引用
back返回最后一个元素的引用
data指向内部数据的一个指针
迭代器上面讲过了
范围forC++11支持更简洁的范围for新遍历方式

        operator[]

        operator[]有边界检查,通过断言检查 

        at

        at功能与operator相似,会主动检查边界并通过抛异常报错 

        front

        返回第一个元素 

        back

        返回最后一个元素

        data

        返回底层的指针。 

vector的容器操作

容量空间接口说明
size获取数据个数
max_size获取向量可容纳的最大值
capacity获取容量大小
empty判断容器是否为空
resize改变vector的size
reserve改变vector的capacity

shrink_to_fit

获得容器剩余可以容纳的最大元素个数

        capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的g++是按2倍增长的

        这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。

         vs是PJ版本STL,g++是SGI版本STL。

        reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。resize在开空间的同时还会进行初始化,影响size。

        size

        max_size

        同string一样,max_size仅仅作为理论值而存在

      capacity  

        empty

        resize

       resize主要针对size进行扩容

        功能:

1扩容(空余位置会进行插入数据)

2空间够直接会插入数据

3空间不够的时候删除数据

        reserve

       reserve针对于capacity进行扩容

        当我知道你需要多少空间的时候提前预留空间可以减少扩容

        shrink_to_fit

        

        缩容。一种时间换空间的方式,一般情况下不用

vector与string的区别

        

        如上图所示,在底层上,string与vector是很相似的。string底层是数组,vector也是数组

        但是vector<char>是不能代替string的。尽管也有vector<string>的写法,任意类型纯可以存储到vector里面

        但是vector末尾没有‘\0’,写字符串的时候无法与C语言兼容,也就无法替代string

vector增删查改

vector增删查改接口的说明
push_back尾插
pop_back尾删
find查找(算法模块的,不是vector接口)
insert在pos位置之前插入val
erase删除pos位置的数据
swap交换两个vector的数据
operator[]像数组一样访问vector
emplace构造并插入元素
emplace_back末尾构造并插入新元素
clear清清除容器所有的大小并使得容器大小为0
assign向向量分配新的内容,替换当前内容并分配新的空间

        push_back

        尾部插入数据 

#include <iostream>
#include <vector>
#include <string>
using namespace std;
void test3()
{string s1 = ("hello world");vector<string> v1;v1.push_back(s1);v1.push_back("goodbye");//用范围for遍历更加方便for (auto s : v1){cout << s << " ";}cout << endl;}
int main()
{test3();return 0;
}

结果为:

 

        但是这种写法效率比较低。因为这样会有string的拷贝构造,而且还是深拷贝

#include <iostream>
#include <vector>
#include <string>
using namespace std;
void test3()
{string s1 = ("hello world");vector<string> v1;v1.push_back(s1);v1.push_back("goodbye");//用范围for遍历更加方便for (const auto& s : v1){cout << s << " ";}cout << endl;}
int main()
{test3();return 0;
}

        push_back构造方式:

void test5()
{vector<Boogiepop>v1;Boogiepop b1(1, 2);//有名对象v1.push_back(b1);//匿名对象v1.push_back(Boogiepop(1, 2));//多参数隐式类型转换v1.push_back({1,3});}

        pop_back

        尾部删除数据‘

        find

        vector和list的find函数都是通过算法库来查找的,使用的时候需要包含头文件<algorithm>

        但是为什么string不用find函数而是自己要做一个呢?因为string的更加复杂

        insert

        

         erase

        以上两个函数应用的代码举例 

void test2()
{vector<int> v1(5, 0);v1.insert(v1.begin() + 2, 3);for (size_t i = 0;i < v1.size();i++){cout << v1[i] << " ";}cout << endl;auto it = find(v1.begin(), v1.end(), 5);if (it != v1.end()){cout << "找到元素" << endl;}else{cout << "未找到元素" << endl;}v1.erase(v1.begin());for (size_t i = 0;i < v1.size();i++){cout << v1[i] << " ";}
}

 结果为:

        swap

 

        clear 

 

        emplace

 

 emplace_back                   

include <iostream>
#include <vector>
#include <string>
using namespace std;
void test4()
{vector<int>v1{ 1,2,3,4,5,6,7,8,9,10 };v1.push_back(1);v1.emplace_back(1);for (const auto& i : v1){cout << i << " ";}cout << endl;
}
int main()
{test4();return 0;
}

        emplace_bakc可以用以下方式构造

void test5()
{//有名对象v1.emplace_back(b1);//匿名对象v1.emplace_back(Boogiepop(1, 2));//多参数隐式类型转换不能用(涉及到底层,比较麻烦)//但是可以用这种方式构造v1.emplace_back(1, 3);//这样效率更高//直接构造,不是拷贝构造,传构造Boogpop的参数,效率更高
}

        更好的遍历方式:结构化绑定

void test5()
{vector<Boogiepop>v1;Boogiepop b1(1, 2);//有名对象v1.emplace_back(b1);//匿名对象v1.emplace_back(Boogiepop(1, 2));//多参数隐式类型转换不能用(涉及到底层,比较麻烦)//但是可以用这种方式构造v1.emplace_back(1, 3);//这样效率更高vector<Boogiepop>::iterator it = v1.begin();/*  while (it != v1.end()){cout << (*it)._a1<< " " << (* it)._a2<< endl;++it;}*///迭代器:更方便的方式while (it != v1.end()){cout << it->_a1 << " " << it->_a2 << endl;++it;}cout << endl;//C++11:范围forfor (const auto& b : v1){cout << b._a1 << " " << b._a2 << endl;}cout<<endl;//C++17:结构化绑定for (auto [x,y]:v1){cout<<x<<" "<<y<<endl;}
}

部分读者可能不支持结构化绑定的语法,可以这么修改

        1首先右键项目,找到属性:

        2.然后在此页面中找到C++ 语言标准,更改至17及其以上的版本(如果没有请更换更高级版本的编辑器)

        上面的代码还可以加引用。

//C++17:结构化绑定
auto &[x,y] = b1;
for (auto &b1:v1)
{cout<<x<<" "<<y<<endl;
}

        加引用减少了拷贝,效率更高了

        也可以这么写

 //C++17:结构化绑定for (auto &[x,y] : v1){cout<<x<<" "<<y<<endl;}

        当你访问的是一个结构体或者类的时候可以用这种方式

assign  

vector的非成员函数重载

        vector的关系运算符重载

         swap函数

内存池函数 

模板专用化 

         成员类:引用

        成员函数:

        flip

        swap 

        类模板特化 

一些题目:

        杨辉三角

题目:

C++ 写法:

 

      只出现一次的数字1

题目:

答案:

        关于vector的使用目前我们就讲到这里,后续我们将进一步学习vector的底层模拟实现。敬请期待。

        在这里各位读者朋友点一个赞,谢谢

封面图自取:

相关文章:

  • Milvus向量Search查询综合案例实战(下)
  • 即插即用的全新算法改进策略——引导学习策略:一种用于元启发式算法设计和改进的新型更新机制
  • C语言| 函数参数传递指针
  • 如何使用 poetry 创建虚拟环境,VSCode 如何激活使用 Poetry 虚拟环境(VSCode如何配置 Poetry 虚拟环境)
  • 2025年渗透测试面试题总结-匿名[校招]安全服务工程师(题目+回答)
  • GitLab CI流水线权限隔离
  • jsrpc进阶模式 秒杀js前端逆向问题 burp联动进行爆破
  • 大模型应用开发第五讲:成熟度模型:从ChatGPT(L2)到未来自主Agent(L4)
  • AI觉醒前兆,ChatGPT o3模型存在抗拒关闭行为
  • 【Linux学习笔记】深入理解动静态库本质及其制作
  • 题目 3316: 蓝桥杯2025年第十六届省赛真题-数组翻转
  • CSS选择器:has使用示例
  • 通过mailto:实现web/html邮件模板唤起新建邮件并填写内容
  • Linux 第十二讲 --- 进程篇(二) 初识进程
  • KONG根据请求参数限流
  • QT使用cmake添加资源文件闪退,创建了qrc文件不能添加的问题解决
  • 【Elasticsearch】track_total_hits
  • 设计模式25——中介者模式
  • Python列表深浅拷贝详解:原理、区别与应用场景
  • 期货反向跟单—交易规则设计(三)交易时长
  • 北京工程工程建设交易信息网站/windows优化大师要会员
  • 沈阳建设银行网站首页/深圳专业seo
  • 政府网站建设 绩效考核4%/网站推广技巧
  • asp网站制作教程/湖北seo整站优化
  • 如何把自己做的网站放到内网/yandex搜索入口
  • 南阳网站建设/如何做营销策划方案