STL等容器结构选型时,针对预先确定长度的线性结构,采用array代替vector
【说明】 std::array 是在 C++11 标准中增加的 STL 容器,它的设计目的是提供与原生数组类似的功能与性能。针对元素个数确定且数据量不是很大的场景,建议使用 std::array 代替 std::vector。
【原理】 C++11 新增了模板类 array,它位于名字空间 std 中。std::vector 和 std::array 是两种常见的原生数组替代品,其功能差异主要体现为:
- std::vector:元素占用的空间是在 堆 上分配的,大小可以改变,每当容器需要扩大时,都会按照相同的系数进行扩大,内存连续,可随机存取。是对动态数组的封装。封装后占用的内存比封装前要大,一般是多两个指针的大小。
- std::array:元素占用的空间是在 栈 上分配的,大小固定不变,内存连续,可随机存取。是对静态数组的封装。封装后占用的内存与封装前是一样的。
应该如何选择使用哪一个容器?有以下经验:
- 如果元素个数确定且数据量不是很大时(和直接使用数组的要求相同,避免栈溢出),应使用 std::array,在存取速度和内存占用上,相对于静态数组是没有消耗的,且类型安全。
- 如果元素个数不确定,但是元素个数的变化频率比较低,应使用 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
【注意事项】 不涉及
父主题: C++语言