鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

STL等容器结构选型时,针对预先确定长度的线性结构,采用array代替vector

【说明】 std::array 是在 C++11 标准中增加的 STL 容器,它的设计目的是提供与原生数组类似的功能与性能。针对元素个数确定且数据量不是很大的场景,建议使用 std::array 代替 std::vector。

【原理】 C++11 新增了模板类 array,它位于名字空间 std 中。std::vector 和 std::array 是两种常见的原生数组替代品,其功能差异主要体现为:

  • std::vector:元素占用的空间是在 上分配的,大小可以改变,每当容器需要扩大时,都会按照相同的系数进行扩大,内存连续,可随机存取。是对动态数组的封装。封装后占用的内存比封装前要大,一般是多两个指针的大小。
  • std::array:元素占用的空间是在 上分配的,大小固定不变,内存连续,可随机存取。是对静态数组的封装。封装后占用的内存与封装前是一样的。

应该如何选择使用哪一个容器?有以下经验:

  1. 如果元素个数确定且数据量不是很大时(和直接使用数组的要求相同,避免栈溢出),应使用 std::array,在存取速度和内存占用上,相对于静态数组是没有消耗的,且类型安全。
  2. 如果元素个数不确定,但是元素个数的变化频率比较低,应使用 std::vector。存取速度上相对于动态数组是没有消耗的。但是当元素个数达到 std::vector 的最大容量时,std::vector 会重新分配新的足够的空间来储存数据,并将旧的数据拷贝到新分配的空间中,这会带来一定的消耗。

std::array 相比 std::vector,支持的方法差异如下:

Function

std::array

std::vector

constructor

no

yes

destructor

no

yes

empty()

yes

yes

size()

yes

yes

resize()

no

yes

capacity()

no

yes

reserve()

no

yes

max_size()

yes

yes

erase()

no

yes

clear()

no

yes

operator=

yes

yes

operator<

yes

yes

operator==

yes

yes

operator[]

yes

yes

at()

yes

yes

front()

yes

yes

back()

yes

yes

push_back()

no

yes

pop_back()

no

yes

assign()

yes

yes

insert()

no

yes

swap()

yes

yes

数组、vector、array用法举例:
int main(void)
{
    /* 1.构造方式
     * vector: 有多种构造方式,不需要定义元素个数;除常见的初始化方式外,还可以通过vector和数组构造新的vector
     * array: 定义时必须指定array的大小,可通过array构造新的array,不可使用数组构造
     * 数组: 定义时必须指定array的大小,使用{}初始化
     */
     std::vector<int> myVector = { 1, 2, 3, 4, 5 };
     std::array<int, 5> myArray = { 1, 2, 3, 4, 5 };
     int myInt[5] = { 1, 2, 3, 4, 5 };

    /* 2.访问方式
     * 三者均可通过下标运算符[]对元素进行操作,vector和array还可以通过at/front/back进行操作
     */
    std::cout << setw(10) << "vector" << setw(10) << "array" << setw(10) << "数组" << std::endl;
    for (int i = 0; i < 5; i++){
        std::cout << setw(10) << myVector.at(i) << setw(10) << myArray.at(i) << setw(10) << myInt[i] << std::endl;
    }

    /* 3.遍历方式
     * vector和array可以通过正向和反向迭代器对元素进行遍历
     */
    std::cout << "=============正向迭代器遍历=========="<< std::endl;
    for (auto it = myArray.begin(); it != myArray.end(); ++it) {
        std::cout << *it << std::endl;
    }
    std::cout << "=============反向迭代器遍历==========" << std::endl;
    for (auto it = myArray.rbegin(); it != myArray.rend(); ++it) {
        std::cout << *it << std::endl;
    }

    /* 4.增删元素
     * vector可以通过push_back/pop_back/emplace/emplace_back/insert动态增删元素
     * array和数组无法实现动态增删元素
    */
    myVector.push_back(6);
    myVector.emplace_back(7);
    auto it = myVector.end();
    myVector.insert(it, { 8, 9 }); // 在尾部插入元素,可通过it改变插入位置,也可以插入多个元素
    myVector.pop_back();
    std::cout << "=============动态增删元素============" << std::endl;
    for (auto it : myVector) {
        std::cout << *it << std::endl;
    }

    return 0;
}
上述代码运行结果:
vector     array      数组
         1         1         1
         2         2         2
         3         3         3
         4         4         4
         5         5         5
=============正向迭代器遍历==========
1
2
3
4
5
=============反向迭代器遍历==========
5
4
3
2
1
=============动态增删元素============
1
2
3
4
5
6
7
8

【注意事项】 不涉及