【C++】vector的介绍和使用

news2025/1/24 14:30:45

​🌠 作者:@阿亮joy.
🎆专栏:《吃透西嘎嘎》
🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述

目录

    • 👉vector 的介绍👈
    • 👉vector 的使用👈
      • vector 的构造函数和遍历
      • vector 空间增长问题
    • 👉vector 动态二维数组的理解👈
    • 👉vector 的增删查改👈
    • 👉总结👈

👉vector 的介绍👈

在这里插入图片描述

  1. vector是表示可变大小数组的序列容器。
  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自 动处理。
  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小 为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增 长。
  6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习。

👉vector 的使用👈

vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。

vector 的构造函数和遍历

这里是引用

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

vector的构造和遍历代码演示

void vectorTest1()
{
    vector<int> first;                                // empty vector of ints
    vector<int> second(4, 100);                       // four ints with value 100
    vector<int> third(second.begin(), second.end());  // iterating through second
    vector<int> fourth(third);                       // a copy of third
    
    // 用数组来初始化
    // the iterator constructor can also be used to construct from arrays:
    int myints[] = { 16,2,77,29 };
    vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));
    // []+下标遍历,只有string和vector支持这种方式
    for (size_t i = 0; i < fifth.size(); ++i)
    {
        cout << fifth[i] << ' ';
    }
    cout << endl;

    // 迭代器遍历
    vector<int>::iterator it = fifth.begin();
    while (it != fifth.end())
    {
        cout << *it << ' ';
            ++it;
    }
    cout << endl;

    // 范围for遍历,底层为迭代器
    for (auto e : fifth)
    {
        cout << e << ' ';
    }
    cout << endl;
}

在这里插入图片描述
vector iterator

iterator的使用接口说明
begin + end(重点)获取第一个数据位置iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

在这里插入图片描述

在这里插入图片描述

为什么vector<char> strstring str无法取代对方

  1. 网络上发送一段字符串,字符串需要以'\0'结束,而 string 无法被发送。
  2. string 支持比较字符串大小,比较常见;而 vector 的比较大小不常见,也没有什么意义。
  3. 函数接口不完全相同。如 string 类有 +=,而 vector 没有 +=。

vector 空间增长问题

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize(重点)改变vector的size
reserve (重点)改变vector的capacity

reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。

resize在开空间的同时还会进行初始化,影响size

reserve 函数接口不会使 vector 缩容,缩容一般是异地缩容,缩容比较大。

在这里插入图片描述
在这里插入图片描述
resize 的函数接口也能说明内置类型需要有构造函数。

在这里插入图片描述

注:在程序里看到的空间都是虚拟的进程空间,进程会提高页表映射和物理内存建立映射。只有在内核层通过页表才能找到物理地址。

注:reserve 只会修改capacity,不会影响size。

在这里插入图片描述
为什么上面的程序会报错呢?因为 reserve 函数将 capacity改成了10,而 size 还是0,所以就会越界访问,触发了 [ ]运算符重载的 assert 报错。

我们可以将上面的代码,改成下面代码的样子,就不会出现这个问题了。

void vectorTest3()
{
    vector<int> v;
    v.reserve(10);
    // 或者将v.reserve(10)换成v.resize(10)
    for (size_t i = 0; i < 10; ++i)
    {
        //v[i] = i;
        v.push_back(i);
    }
}

测试 vector 的默认扩容机制

void TestVectorExpand()
{
    size_t sz;
    vector<int> v;
    sz = v.capacity();
    cout << "making v grow:\n";
    for (int i = 0; i < 100; ++i)
    {
        v.push_back(i);
        if (sz != v.capacity())
        {
            sz = v.capacity();
            cout << "capacity changed: " << sz << '\n';
        }
    }
}

VS的运行结果

在这里插入图片描述
Linux的运行结果

在这里插入图片描述

capacity的代码在VS和g++下分别运行会发现,VS下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。VS是PJ版本STL,g++是SGI版本STL。

为什么扩容多数扩2倍

  • 2 倍比较合适
  • 每次扩少了,会导致频繁扩容
  • 每次扩多了,用不完,存在空间浪费

如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够,就可以避免边插入边扩容导致效率低下的问题了。

void TestVectorExpandOP()
{
    vector<int> v;
    size_t sz = v.capacity();
    v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
    cout << "making bar grow:\n";
    for (int i = 0; i < 100; ++i)
    {
        v.push_back(i);
        if (sz != v.capacity())
        {
            sz = v.capacity();
            cout << "capacity changed: " << sz << '\n';
        }
    }
}

在这里插入图片描述

在这里插入图片描述
shift_to_fit缩容

在这里插入图片描述
释放空间由于内存管理的一些原因,不允许分段释放空间,只能整体释放,一般为异地缩容。

👉vector 动态二维数组的理解👈

LeetCode 杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

在这里插入图片描述

C语言题解

int** generate(int numRows, int* returnSize, int** returnColumnSizes) 
{
    int** ret = malloc(sizeof(int*) * numRows); // 指针数组
    *returnSize = numRows; // 指针数组元素的个数
    *returnColumnSizes = malloc(sizeof(int) * numRows); // returnColumnSizes为一级指针的地址
    for (int i = 0; i < numRows; ++i) 
    {
        ret[i] = malloc(sizeof(int) * (i + 1)); // 让指针数组里的指针都指向一块空间
        (*returnColumnSizes)[i] = i + 1;    // 每一行元素的个数
        ret[i][0] = ret[i][i] = 1;
        for (int j = 1; j < i; ++j) 
        {
            ret[i][j] = ret[i - 1][j] + ret[i - 1][j - 1];
        }
    }
    return ret;
}

在这里插入图片描述

C++题解

class Solution 
{
public:
    vector<vector<int>> generate(int numRows) 
    {
        vector<vector<int>> vv;
        vv.resize(numRows);

        for(size_t i = 0; i < vv.size(); i++)
        {
        	// vv[i]的类型为vector<int>
            vv[i].resize(i + 1); // 开辟空间
            vv[i][0] = vv[i][vv[i].size()-1] = 1;  
        }

        for(size_t i = 0; i < vv.size(); i++)
        {
            for(size_t j = 1; j < i; j++)
            {
                vv[i][j] = vv[i-1][j-1] + vv[i-1][j];
            }
        }
        return vv;
    }
};

在这里插入图片描述

👉vector 的增删查改👈

vector增删查改接口说明
push_back(重点)尾插
pop_back (重点)尾删
find查找(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[] (重点)像数组一样访问
assign给vector赋值
clear清空数据,size修改为0,capacity保持不变

operator[ ]和 at 的相同和区别

在这里插入图片描述

在这里插入图片描述
at() 函数和 [] 运算符的重载,两者都可以得到相应下标的值,并且两者都会去做边界检查。当发生越界行为时,at 是抛异常,operator[] 是报出 assert 错误。assert 断言在 Release 版本下会被优化掉,不会起作用。

补获异常

在这里插入图片描述

函数接口什么时候用 const 修饰,什么时候不需要用 const 修饰。

在这里插入图片描述

assign

在这里插入图片描述

void vectorTest4()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);

    for (auto e : v)
    {
        cout << e << ' ';
    }
    cout << endl;

    v.assign(10, 1);
    for (auto e : v)
    {
        cout << e << ' ';
    }
    cout << endl;

    string s("hello world");
    v.assign(s.begin(), s.end());
    for (auto e : v)
    {
        cout << e << ' ';
    }
    cout << endl;
}

在这里插入图片描述
注:assign的迭代器赋值,迭代器可以是任意类型的迭代器。

在这里插入图片描述

insert

在这里插入图片描述
在这里插入图片描述
注:string 和 vector 可以用迭代器 + 数字的玩法,而 list 没有。因为 string 和 vector 的空间是连续的,而 list 的空间是不连续的。string 和 vector 的正向迭代器为指针,而 list 的迭代器不是指针。

find

在这里插入图片描述
注:find 函数是算法库里的函数,并不是 vector 的成员函数(因为每个容器有 find 函数,且功能都一样,所以就就设计成库函数了),使用时需要包algorithm头文件。

在这里插入图片描述
那为什么 string 类不直接复用算法库的find函数,要自己设计呢?因为 string 类可能要查找一个子串。

swap
在这里插入图片描述

在这里插入图片描述

注:vector 有专门的模板交换函数,只要是避免使用std::swap这个函数,因为这个函数要3次深拷贝。

在这里插入图片描述
注:编译器会调用更加匹配的函数接口。

👉总结👈

以上就是 vector 的介绍和常见接口的使用,下一篇博客将会给大家讲解 vector 的模拟实现。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40124.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【课设/毕业设计】电力系统潮流计算(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

相控阵天线(九):平面阵列天线综合(不可分离型切比雪夫分布、圆口径泰勒综合、可分离型分布)

目录简介不可分离型分布不可分离型切比雪夫圆口径泰勒综合可分离型分布可分离切比雪夫综合可分离泰勒综合简介 按行、列排列的可分离型矩形平面阵&#xff0c;其阵因子是两个正交排列的直线阵阵因子的乘积。可分离的平面阵方向图在两个主面内是满足预期副瓣电平的&#xff0c;…

SpringMVC学习笔记(一)

目录 一、什么是SpringMVC ? 二、Spring MVC项目的连接(用户 和 程序 的 映射) 三、获取参数的功能的实现 传递较少数量的参数&#xff1a; 通过对象传递大量参数&#xff1a; 获取表单参数&#xff1a; 获取Json对象 上传文件&#xff1a; &#x1f514;一点补充 一、…

家用 NAS 服务器搭建 | 前篇

1、前言 最近一段时间都在折腾家用 NAS 服务器&#xff0c;NAS 系统从最开始选择安装开源的 OMV&#xff08;OpenMediaVault&#xff09;、万由U-NAS&#xff0c;最终决定使用黑群晖。硬件也是一步步从旧笔记本、拆旧笔记本改nas样式、最终也是到万由410机箱。 家庭nas服务器可…

unity rtsp 视频渲染(一)

unity unity 可以说是一个不错的工具&#xff0c;建立三维的场景非常方便&#xff0c;下面我们建立一个三维的场景&#xff0c;并且在三维的场景中和场景外分别建立系统去播放视频。所谓场景内就是在三维中播放视频&#xff0c;场景外就是在三维场景前表面的二维平面中播放视频…

Go-Excelize API源码阅读(三十六)——SetSheetRow、InsertPageBreak

Go-Excelize API源码阅读&#xff08;三十六&#xff09;——SetSheetRow、InsertPageBreak 开源摘星计划&#xff08;WeOpen Star&#xff09; 是由腾源会 2022 年推出的全新项目&#xff0c;旨在为开源人提供成长激励&#xff0c;为开源项目提供成长支持&#xff0c;助力开发…

公司信息系统架构建设规划

企业的信息化建设的基础是构建企业的信息系统架构&#xff08;也可称之为信息化架构&#xff09;&#xff0c;信息系统架构又由应用架构、数据架构、技术架构和治理架构4部分组成&#xff0c;本建议书主要以技术架构、应用架构以及技术架构为对象加以说明。 4.1公司信息系统架…

《MongoDB》Mongo Shell中基本操作-ObjectId和文档创建详解

前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 来个关注吧&#xff0c;点个赞…

R语言对用电负荷时间序列数据进行K-medoids聚类建模和GAM回归

通过对用电负荷的消费者进行聚类&#xff0c;我们可以提取典型的负荷曲线&#xff0c;提高后续用电量预测的准确性&#xff0c;检测异常或监控整个智能电网&#xff08;Laurinec等人&#xff08;2016&#xff09;&#xff0c;Laurinec和Luck&#xff08; 2016&#xff09;&…

JavaScript正则表达式加密

正则表达式可以加密吗&#xff1f; 是的&#xff0c;可以。起码可以确定的是在JavaScript编程中是可以的。 正则表达式加密有什么用&#xff1f; 可以隐藏一些重要的、私密的字符串内容&#xff0c;使代码的逻辑、秘密不容易被人窥探。 正则表达式加密示例 例如&#xff1…

1536_AURIX_TriCore内核架构_Trap

全部学习汇总&#xff1a; GreyZhang/g_tricore_architecture: some learning note about tricore architecture. (github.com) 近段时间一直在跟trap打交道&#xff0c;但是处理得毫无头绪&#xff0c;因此找出来了这一章节看一下。暂时&#xff0c;这方面稍微有了一点框架感&…

观世界赛事,品足球人生--2022世界杯

观世界赛事&#xff0c;品足球人生 – 2022世界杯 1.卡塔尔世界杯百科 2022年卡塔尔世界杯&#xff08;英语&#xff1a;FIFA World Cup Qatar 2022&#xff09;是第二十二届世界杯足球赛&#xff0c;是历史上首次在卡塔尔和中东国家境内举行、也是第二次在亚洲举行的世界杯足…

iwebsec靶场 SQL注入漏洞通关笔记7- 空格过滤绕过

系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1- 数字型注入_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2- 字符型注入&#xff08;宽字节注入&#xff09;_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记3- bool注入&#xff08;布尔型盲注&#…

关于mac上如何U盘

关于mac上如何U盘 背景 使用macbook的大概都会遇到 “如何连接U盘” 的问题&#xff0c;网上会搜到很多教程&#xff0c;我觉得很多都不太实用。 首先这个需求是有的&#xff0c;但是对很多人来说很低频几个月用不到一次&#xff0c;所以得找个顺手靠谱的方法。下面是我经历…

【机器学习入门项目10例】(十):PCA降维:简易人脸识别模型

🌠 『精品学习专栏导航帖』 🐳最适合入门的100个深度学习实战项目🐳🐙【PyTorch深度学习项目实战100例目录】项目详解 + 数据集 + 完整源码🐙🐶【机器学习入门项目10例目录】项目详解 + 数据集 + 完整源码🐶🦜【机器学习项目实战10例目录】项目详解 + 数据集 +

C++——电话号码的字母组合问题

文章目录电话号码的字母组合题目链接思路&#xff1a;代码&#xff1a;调试演示电话号码的字母组合 题目链接 思路&#xff1a; 首先使用string类的数组存储每个数字对应的所有可能的字母&#xff0c;然后进行回溯操作。 string arr[] { "","","…

分享88个NET源码,总有一款适合您

链接&#xff1a;https://pan.baidu.com/s/1dPlj8w-rvVQXuJOHPO6tBA?pwddj0d 提取码&#xff1a;dj0d 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载后可以看到。 启明星Appform员工请假系统 25175云酒店管…

微模块化炙手可热,数据中心走向智能化取胜

近年来&#xff0c;“微模块化”成为数据中心领域炙手可热的话题。 Gartner《企业数据中心未来趋势报告》预测&#xff0c;AI、5G、新型电池、模块化设计思想等将改变数据中心的未来&#xff0c;数据中心将走向分散化&#xff0c;并且预计到2025年&#xff0c;微数据中心的数量…

(附源码)python电影院信息管理系统 毕业设计 021844

电影院信息管理系统的设计与实现 摘 要 在信息飞速发展的今天&#xff0c;网络已成为人们重要的信息交流平台。电影院每天都有大量的信息需要通过网络发布&#xff0c;为此&#xff0c;本人开发了一个基于B/S&#xff08;浏览器/服务器&#xff09;模式的电影院信息管理系统。 …

你的NET程序需要保护吗?Agile.net 6.6.X 注入式Crack

Agile.net 使用专利技术将 MSIL 代码转换为虚拟操作码&#xff0c;只有安全的虚拟机才能理解。虚拟机直接处理虚拟操作码&#xff0c;模拟原始代码行为而不将代码转换回其原始形式。破坏保护成为NP完全问题&#xff0c;从而使Agile.net成为唯一保证您的代码不会被破坏的混淆器&…