• C++ vector容器 常用 API 操作


    1 空间满了之后,自动开辟

    vector未雨绸缪机制,满了之后,会自动了扩充为原来的2倍

    (提高效率,避免频繁”配置新空间-数据移动-释放旧空间”)

    在这里插入图片描述

    在这里插入图片描述

    作者在qt上运行的,我在VS上运行,中止

    int main() {
    
        vector v;//最初容器没有元素,容量为空
        cout << "容量" << v.capacity() << endl;
    
        vector::iterator it = v.begin();
        int i = 0;
        int count = 0;
    
        for ( i = 0; i < 1000; i++) {
            v.push_back(i);//插入第一个元素,开辟1空间;插入第二个元素,开辟2空间;插入第三个元素,开辟4空间。。。每次二倍
            if (it != v.begin()) { //如果不相等,说明又开辟了新空间,v.begin指向新空间的开头;
                count++;
                cout <<"开辟空间容量: " << v.capacity() << endl;
                it = v.begin();//it记录当前空间的开头
           }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    2 事先预留空间

    reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
    
    • 1

    3 vector 大小操作

    size();//返回容器中元素的个数 empty();//判断容器是否为空 
    resize(int num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短, 则末尾超出容器长度的元素被删除。 
    resize(int num, elem);//重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置。如果 容器变短,则末尾超出容器长>度的元素被删除。 
    capacity();//容器的容量 
    reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4 常用赋值操作

    void printVectorInt(vector& v) {
        vector::iterator it = v.begin();
        for (; it != v.end(); it++)
            cout << *it << " ";//看着像指针,其实不是指针
        cout << endl;
    }
    
    void test2() {
        vector v1(5,100);//构造函数将 n 个 elem 拷贝给本身。
        printVectorInt(v1);
    
        vector v2(v1.begin(),v1.end());
        printVectorInt(v2);
    
        vector v3 = v1;
        printVectorInt(v3);
    
        vector v4(v1);
        printVectorInt(v4);
    
        vector v5;
        v5.assign(v1.begin(), v1.end());//将[beg, end)区间中的数据拷贝赋值给本身
        printVectorInt(v5);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    5 容器互换 swap(vec)

    swap(vec);// 将 vec 与本身的元素互换。
    
    • 1

    void test3() {
    vector v6 = { 1,2,3,4,5,6 };
    vector v7 = { 10,12 };

    printVectorInt(v6);
    printVectorInt(v7);
    
    //v6,v7交换
    v6.swap(v7); //同 swap(v6,v7);
    
    printVectorInt(v6);
    printVectorInt(v7);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    }
    在这里插入图片描述

    6 巧用 swap 收缩内存空间

    C++ vector容器的swap方法(容器互换)

    假如预留了一个较大空间,但实际上只用了很少一部分,现在想释放多余空间。
    在这里插入图片描述
    当我们将一个容量为一百万的容器,使用 resize(5) 函数重新指定大小为5的时候,它并不是向上图一样,就剩下5个空间,将其余空间释放掉,而是下图这种状态:

    在这里插入图片描述
    resize()做的操作大概是直接修改了数据量 大小,让我不能访问后面的数据,而容量还是100万。

    这就是问题所在,重新指定大小后,这么大的空间就浪费掉了。

    而swap()可以解决这个问题。

    用法如下:

    vector(v).swap(v);	//v是容器名
    
    • 1

    也就是说通过该语句,可以将v中空闲的空间释放掉。

    这条语句可以分为两个部分:
    vector(v) 和 .swap(v) 两部分

    首先看第一部分,vector(v)
    首先,这条语句,通过 拷贝构造函数 创建了一个 匿名对象 ,这个匿名对象拥有v的全部数据,但是,没有空闲的空间,也就是说,这个匿名对象的 容量 和 数据量 是相等的。如下图:
    在这里插入图片描述

    void test4() {
        vector v1;
        v1.reserve(1000);
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(i);
        }
        cout << "v1的容量:" << v1.capacity() << endl;
        cout << "v1的大小:" << v1.size() << endl;
    
        v1.resize(3);//resize只能修改大小 不能修改容量
        cout << "v1.resize后的容量:" << v1.capacity() << endl;
        cout << "v1.resize后的大小:" << v1.size() << endl;
    
        vectorv2(v1);
    
        cout << "v2的容量:" << v2.capacity() << endl;
        cout << "v2的大小:" << v2.size() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述
    所以经过 vector(v) 创建出来的匿名对象是没有空闲空间的,此时,通过 .swap(v) 调用该匿名类的swap()方法,交换v与匿名类的内容,结果如下:

    在这里插入图片描述
    最后,该行语句指向完毕,匿名类被析构,空间被释放。

    最终结果就是,原容器中的空位被释放

    void test5() {
        vector v1;
        v1.reserve(1000000);//注意:是预留reserve,不是重置 resize
        for (int i = 0; i < 5; i++)
        {
            v1.push_back(i);
        }
      
        cout << "v1的容量:" << v1.capacity() << endl;
        cout << "v1的大小:" << v1.size() << endl;
    
        vector(v1).swap(v1); //不能写成v1.swap(v1);//v1自己与自己交换,结果没变化
    
        cout << "\nswap释放空间后,v1的容量和大小:" << endl;
        cout << "v1的容量:" << v1.capacity() << endl;
        cout << "v1的大小:" << v1.size() << endl;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    7 自定义数据类型(存放、遍历、排序)

    //vector存放自定义数据类型
    class Person
    {
    public:
        friend void printVectorPerson(vector& v);//m_Name、m_Age是私有属性,要有元
        friend bool compare(Person ob1, Person ob2);
        Person(string name, int age)
        {
            this->m_Name = name;
            this->m_Age = age;
        }
    private:
        string m_Name;
        int m_Age;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    遍历容器中的数据

    对象成员m_Name、m_Age是私有属性,故要在public定义有元之后,才可以使用

    public:
    friend void printVectorPerson(vector& v);
    friend bool compare(Person ob1, Person ob2);

    //遍历容器中的数据
    void printVectorPerson(vector& v) {
        vector::iterator it = v.begin();
        for (; it != v.end(); it++)
            // *it == Person
            cout << "姓名:" << (*it).m_Name << "  年龄: " << (*it).m_Age << endl;//这两种输出都可以,但建议使用这种;
             //cout << "姓名:" << it->m_Name << "    年龄:" << it->m_Age << endl;//这种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错
        cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    //排序比较方式
    ob1,ob2对象成员m_Name、m_Age是私有属性,故要在public定义有元之后,才可以使用

    public:
    friend void printVectorPerson(vector& v);
    friend bool compare(Person ob1, Person ob2);

    bool compare(Person ob1, Person ob2) {
        return ob1.m_Age < ob2.m_Age;//按年龄升序
    }
    
     //排序,compare是排序方式,定义在上面
       sort(v.begin(),v.end(),compare);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试调用

    void test6()
    {
        //创建一个vector容器,(数组)
        vector v;
        Person p1("a", 50);
        Person p2("b", 20);
    
        //向容器中插入数据
        v.push_back(p1);
        v.push_back(p2);
        //向容器中插入数据
        v.push_back(Person("c", 30));
        v.push_back(Person("d", 40));
    
        //遍历容器中的数据
        printVectorPerson(v);
    
        //排序,compare是排序方式,定义在上面
        sort(v.begin(),v.end(),compare);
        //遍历容器中的数据
        printVectorPerson(v);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    下面是容器中的数据打印输出,及按照年龄排序后打印输出
    在这里插入图片描述

    7 迭代器注意事项

    vector::iterator it = v.begin();

    // *it == Person
    这里*it等价Person
    
    • 1
    • 2

    以下两种输出都可以,但建议使用第一种;
    第二种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错;

    cout << "姓名:" << (*it).m_Name << "  年龄: " << (*it).m_Age << endl;//这两种输出都可以,但建议使用这种;
     //cout << "姓名:" << it->m_Name << "    年龄:" << it->m_Age << endl;//这种写法把迭代器当作指针使用了,虽然这里可以,但迭代器毕竟不是指针,复杂的地方会出错
    
    • 1
    • 2
  • 相关阅读:
    【链表OJ 10】环形链表Ⅱ(求入环节点)
    Priv-app permission异常
    elasticsearch 安装教程
    vue实现带有横向和纵向双表头
    声明周期1
    HK32F030MF4P6的Linux GCC工具链开发环境
    隐藏安卓平板状态栏,还你全面屏体验
    【微服务】SpringCloud微服务注册源码解析
    CentOS 8里的这个功能,天翼云SFS弹性文件校准了
    EN 12259-4固定消防系统水马达报警器—CE认证
  • 原文地址:https://blog.csdn.net/m0_51233386/article/details/126473802