2.3、std::array(固定大小数组容器)
什么是std::array?用大白话说
int arr[10];
这样的传统数组。它很快,但有几个“坑”:
- • 它不知道自己有多大,传给函数时会退化成指针,导致无法安全获取长度。
- • 访问越界不会报错,容易引发难查的bug。
- • 它没有成员函数,不能用现代C++的容器接口。
std::array就是为了解决这些问题而生的。它是一个模板类,固定大小,大小在编译时确定,内部就是包了一层传统数组,但提供了更安全、更丰富的操作接口。它不会退化成指针,知道自己的大小,访问越界时还能抛异常(at()
方法),用起来更放心。
设计哲学:安全、固定、兼容
std::array的设计哲学可以总结为:
- • 安全第一:避免C数组的隐式指针退化,防止越界访问,提供边界检查。
- • 固定大小:大小在编译时确定,保证效率和内存连续性,适合对大小有严格要求的场景。
- • 标准容器接口:支持迭代器、
size()
、empty()
、front()
、back()
等接口,和STL算法无缝集成。 - • 轻量无开销:本质上就是包了一层数组,性能几乎和C数组一样,没有动态内存分配。
代码对比:传统数组 vs std::array
#include <iostream>
#include <array>
void printCArray(int* arr, size_t size) {
for(size_t i = 0; i < size; ++i)
std::cout << arr[i] << " ";
std::cout << "\n";
}
void printStdArray(const std::array<int, 5>& arr) {
for(auto elem : arr)
std::cout << elem << " ";
std::cout << "\n";
}
int main() {
// 传统C数组
int cArr[5] = {1, 2, 3, 4, 5};
printCArray(cArr, 5); // 需要手动传大小,容易传错
// std::array
std::array<int, 5> stdArr = {1, 2, 3, 4, 5};
printStdArray(stdArr); // 不用传大小,安全方便
// 越界访问示例
// std::cout << cArr[10] << "\n"; // 未定义行为,可能崩溃或输出垃圾
try {
std::cout << stdArr.at(10) << "\n"; // 抛出异常,安全提示
} catch (const std::out_of_range& e) {
std::cout << "异常捕获:" << e.what() << "\n";
}
return 0;
}
对比解析:
传统数组需要手动传递大小,容易出错,且访问越界不会报错。
std::array自带size()
,访问越界用at()
会抛异常,安全得多。
std::array支持范围for循环,接口更现代。
使用场景和优缺点
适合用std::array的场景:
- • 大小固定且已知:比如存储一周7天的温度,或固定维度的向量。
- • 对性能有要求:栈上分配,连续内存,访问速度快。
- • 需要和STL算法配合:std::array直接支持迭代器,方便调用
std::sort
、std::find
等。 - • 希望代码更安全:防止越界,避免指针退化带来的隐患。
优点总结
- • 安全性高:防止隐式指针退化,
at()
带边界检查。 - • 接口丰富:支持
size()
、empty()
、迭代器等标准容器接口。 - • 性能接近C数组:无动态分配,内存连续。
- • 易于复制和赋值:重载了拷贝构造和赋值运算符。
缺点和限制
- • 大小固定:不能动态扩展,灵活性不如
std::vector
。 - • 初始化稍繁琐:二维数组声明比C数组更冗长。
- • 需要包含头文件:相比C数组多了依赖。
- • 越界检查开销:
at()
有边界检查,release模式下可能被优化掉,debug模式下有性能损失。
错误使用后果
- • 误用
operator[]
越界访问:仍然是未定义行为,可能导致程序崩溃或数据错误。 - • 误以为std::array可以动态扩容:它是固定大小容器,不能
push_back
或resize
,误用会导致编译错误或逻辑错误。 - • 忽略异常捕获:使用
at()
访问时不捕获异常,程序可能异常终止。 - • 滥用二维std::array导致代码臃肿:二维或多维数组声明复杂,影响代码可读性。
总结
std::array是C++11对传统数组的现代化升级,设计上追求安全、固定和标准化,适合固定大小、对性能和安全有要求的场景。它弥补了C数组的缺陷,提供了更丰富的接口和更强的类型安全,且性能几乎无损。理解并合理使用std::array,能让你的C++代码更健壮、更现代。
不过,std::array不是万能的,面对动态大小需求时,还是得用std::vector
。在实际项目中,std::array适合用作固定大小的缓冲区、配置参数容器、数学向量等,避免了裸数组的隐患,提升代码质量。
本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)
阅读剩余
版权声明:
作者:讳疾忌医-note
链接:https://www.1217zy.vip/archives/717
文章版权归作者所有,未经允许请勿转载。
THE END