vector容器

Posted yuehouse

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vector容器相关的知识,希望对你有一定的参考价值。

一、vector容器概念

  • vector是将元素置于一个动态数组(或可变数组)中加以管理的容器,大小会根据元素个数进行自动增长。
  • vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲)。
  • vector容器是一个单口容器,vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时。

二、vector动态增长基本原理

当插入新元素时,如果空间不足,那么vector会重新申请更大的一块内存空间,将原空间数据拷贝到新空间,释放旧空间的数据,再把新元素插入新申请空间。

三、vector常用API

1、vector构造函数

技术分享图片

2、vector常用赋值操作

技术分享图片

3、vector大小操作

技术分享图片

注意:resize 若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

4、vector数据存取操作

技术分享图片

5、vector插入和删除操作

技术分享图片

 

6、巧用swap缩减空间

由于vector的内存占用空间只增不减,比如你首先分配了10,000个字节,然后erase掉后面9,999个,留下一个有效元素,但是内存占用仍为10,000个。所有内存空间是在vector析构时候才能被系统回收。empty()用来检测容器是否为空的,clear()可以清空所有元素。但是即使clear(),vector所占用的内存空间依然如故,无法保证内存的回收。

7、reserve预留空间

技术分享图片

如果知道容器大概要存储的元素个数,那么可以用reserve预留空间。

 

总结:vector是个动态数组,当空间不足的时候插入新元素,vector会重新申请一块更大的内存空间,将旧空间数据拷贝到新空间,然后释放旧空间。vector是单口容器,所以在尾端插入和删除元素效率较高,在指定位置插入,势必会引起数据元素移动,效率较低。

四、案例

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
using namespace std;

void PrintVector(vector<int>& v)
{
    for (vector<int>::iterator it = v.begin();it != v.end();it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//初始化
void test01()
{
    vector<int> v1;//默认构造

    int arr[] = { 10,20,30,40 };
    vector<int> v2(arr, arr + sizeof(arr) / sizeof(int));
    vector<int> v3(v2.begin(), v2.end());
    vector<int> v4(v3);

    PrintVector(v2);//10 20 30 40
    PrintVector(v3);//10 20 30 40
    PrintVector(v4);//10 20 30 40
}

//常用赋值操作
void test02()
{
    //构造函数
    int arr[] = { 10,20,30,40 };
    vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));

    //成员方法
    vector<int> v2;
    v2.assign(v1.begin(), v1.end());

    //重载=号运算符
    vector<int> v3;
    v3 = v2;

    //构造函数
    int arr1[] = { 100,200,300,400 };
    vector<int> v4(arr1, arr1 + sizeof(arr1) / sizeof(int));

    PrintVector(v1);//10 20 30 40
    PrintVector(v2);//10 20 30 40
    PrintVector(v3);//10 20 30 40
    PrintVector(v4);//100 200 300 400

    cout << "------------------" << endl;

    v4.swap(v1);//v4与v1交换,交换原理:只是把内部指向数据的指针进行了交换

    PrintVector(v1);//100 200 300 400
    PrintVector(v2);//10 20 30 40
    PrintVector(v3);//10 20 30 40
    PrintVector(v4);//10 20 30 40

}

//大小操作
void test03()
{
    int arr[] = { 10,20,30,40 };
    vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));

    cout << "size:" << v1.size() << endl;//size:4

    if (v1.empty())
    {
        cout << "空!" << endl;
    }
    else
    {
        cout << "不空!" << endl;//不空
    }

    PrintVector(v1);//10 20 30 40
    v1.resize(2);
    PrintVector(v1);//10 20
    v1.resize(4);
    PrintVector(v1);//10 20 0 0
    v1.resize(6,1);
    PrintVector(v1);//10 20 0 0 1 1

    for (int i = 0;i < 100;i++)
    {
        v1.push_back(i);
    }
    //容量capacity>=元素的个数size
    cout << "元素的个数size:" << v1.size() << endl;//元素的个数size:106
    cout << "容量capacity:" << v1.capacity() << endl;//容量capacity:141
}

//vector存取数据
void test04()
{
    int arr1[] = { 100,200,300,400 };
    vector<int> v4(arr1, arr1 + sizeof(arr1) / sizeof(int));

    //[]取值与at()取值的区别:索引值越界时,at抛异常,[]不抛异常
    for (int i = 0;i < v4.size();i++)
    {
        //cout << v4[i] << " ";
        cout << v4.at(i) << " ";//100 200 300 400        
    }
    cout << endl;

    cout << "front:" << v4.front() << endl;//front:100
    cout << "back:" << v4.back() << endl;//back : 400
}

//vector插入和删除操作
void test05()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    //头插法
    v.insert(v.begin(), 30);
    v.insert(v.end(), 40);

    v.insert(v.begin()+2, 100);//在这里可以用v.begin()+2,是因为:vector支持随机访问
    //支持数组下标的,一般都支持随机访问
    //迭代器可以直接 +某个数 或 -某个数 的操作
    PrintVector(v);//30 10 100 20 40

    //删除
    v.erase(v.begin());
    PrintVector(v);//10 100 20 40
    v.erase(v.begin()+1,v.end());
    PrintVector(v);//10
    v.clear();
    cout << "size:" << v.size() << endl;//size:0
}

//巧用swap缩减空间
void test06()
{
    //vector添加元素 它会自动增长,删除元素的时候,不会自动减少
    vector<int> v;
    for (int i = 0;i < 10000;i++)
    {
        v.push_back(i);
    }

    cout << "size:" << v.size() << endl;//size:10000
    cout << "capacity:" << v.capacity() << endl;//capacity:12138

    v.resize(10);
    cout << "size:" << v.size() << endl;//size:10
    cout << "capacity:" << v.capacity() << endl;//capacity:12138

    //收缩空间:
    //swap技法就是通过交换函数swap(),使得vector离开其自身的作用域,
    //从而强制释放vector所占的内存空间。
    //vector<int>(v):用v去初始化匿名对象,匿名对象会根据v的实际元素个数初始化它自己,
    //然后匿名对象的指针指向与v的指针指向交换,随后匿名对象自动销毁
    vector<int>(v).swap(v);//或者v.swap(vector<int>(v));
    cout << "size:" << v.size() << endl;//size:10
    cout << "capacity:" << v.capacity() << endl;//capacity:10

}

void test07()
{
    //reserve 预留空间
    int num = 0;//统计自动增长的次数
    int* address = NULL;

    vector<int> v;
    //如果知道容器大概要存储的元素个数,那么可以用reserve预留空间
    v.reserve(10000);
    for (int i = 0;i < 10000;i++)
    {
        v.push_back(i);
        if (address != &(v[0]))//通过判断vector内存的首地址是否发生变化可知道是否申请了新的内存
        {
            address = &(v[0]);
            num++;
        }
    }
    cout << "num:" << num << endl;

}

int main(void)
{
    //test01();
    //test02();
    //test03();
    //test04();
    //test05();
    //test06();
    test07();

    return 0;
}

 

以上是关于vector容器的主要内容,如果未能解决你的问题,请参考以下文章

vector向量容器(常用的使用方法总结)

引用向量的部分片段?

STL源代码剖析 容器 stl_vector.h

谈谈vector容器的三种遍历方法

这个代码片段究竟做了啥?

STL—— 容器(vector)元素的删除