【C++STL之vector类概述

2023年 9月 29日 19.9k 0

文章篇幅较长,越3万余字,建议电脑端访问

一、前言

大家好,在上一文中,我们重点介绍了 STL中的string类,明白了如何去操作字符串。本文我们将要来介绍的是STL中的vector类

二、vector的介绍及使用

1、vector的介绍

vector的文档介绍

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

    1)vector类对象的默认成员函数

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

    ① 构造函数

    • 首先的话我们来看构造函数,一共是有三种形式
      • 无参进行构造
      • 放入n个相同数据
      • 根据迭代器区间进行构造

    其中的 allocator 是空间配置器,只是用于分配空间,目的为增加申请释放空间的效率

    在这里插入图片描述

    可以看到对于【vector】来说其为一个 模版类,所以我们在实例化的时候要声明其内置类型

    template  class vector;
    

    接下去,我们就到VS中来测试一下

    void test_vector1()
    {
    	vector v1;
    	vector v2(3, 2);
    
    	string s("abcd");
    	vector v3(s.begin(), s.end());
    }
    
    • 以下是调试后的结果。重点我们可以来说一说最后一种迭代器的方式,有同学看到我们存入进去的明明是a b c d四个字符,但是在调试的时候看到的为什么是97 98 99 100呢,原因就在于我们对于【v3】声明的内置类型为int,但是我们传递进去的却是char,所以在这中间产生了一个 隐式类型转换

    在这里插入图片描述

    • 如果想要看到字符的话正确的形式应该改成下面这样
    vector v3;
    

    💬 那有同学就说了,这个vector v是不是和string s一样呢,存放的都是字符char

    • 这个呢是不可以的,对于前者来说默认是不存在的,需要我们去进行添加,但是对于后者来说是一个字符串,而对于字符串来说结尾是存在
    vector v;
    string s;
    

    💬 此时有同学又问,既然【vector】中可以存放char的话,那可不可以存放string

    • 这个呢肯定是可以滴,因为【vector】是一个模版类,其会根据所传入的类型去做一个自动类型的推导
    vector v;
    

    💬 最后的话再来讲一种初始化的方式,那就是利用我们在C语言阶段所学习过的 指针,虽然表面上利用的是指针的一个偏移量来做的一个初始化工作,但是呢它在底层利用的还是 迭代器 的思维

    void test_vector2()
    {
    	// 利用天然的迭代器 —— 指针进行初始化
    	int a[] = { 1, 2, 3, 4 };
    	vector v2(a, a + 4);
    }
    
    • 一样通过调试来观察一下

    在这里插入图片描述

    ② 拷贝构造

    然后我们再来聊聊拷贝构造

    在这里插入图片描述
    拷贝方式如下:

    vector v1(3, 2);
    vector v2(v1);
    

    在这里插入图片描述

    ③ 赋值重载

    讲完拷贝构造,那赋值重载一定不能少

    在这里插入图片描述

    • 赋值重载用于对已存在的两个 vector 之间进行赋值,就是值之间的拷贝
    v2 = v1;
    

    在这里插入图片描述

    • 因此呢对于不同类型的数据就无法进行赋值
    void test_vector3()
    {
    	vector v1(3, 2);
    
    	vector v2;
    	v2 = v1;
    }
    

    在这里插入图片描述

    2)vector类对象的访问及遍历操作

    ① operator[]

    首先对于访问元素来说的话,最常见的还是 下标 + [ ] 的形式

    • 下面是官方文档中的形式,虽然看起来很复杂,但是读者完全不用理会,会用就可以了
    reference operator[] (size_type n);const_reference operator[] (size_type n) const;
    
    • 由于我在 string 中对这一块已经讲解得很详细了,它们在使用的时候很类似,此处就不细说了
    void test_vector4()
    {
    vector v({ 1,2,3,4,5 });
    for (size_t i = 0; i < v.size(); i++)
    {
    cout

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论