std::array 是对 c 风格静态数组的封装,保留栈分配、固定大小、零开销特性,但提供容器接口(如 size()、at());声明必须显式指定大小,不支持 ctad(c++17 起仍不支持),sizeof 等于元素总大小,访问 operator[] 无边界检查,传参应优先用 const 引用以避免拷贝。

std::array 是什么,和普通数组到底差在哪
它不是新类型,而是对 C 风格静态数组的封装:保留栈上分配、固定大小、零开销特性,但补全了容器接口(size()、begin()、at() 等)。编译期就知道长度,不涉及堆分配,也不带运行时额外存储——sizeof(std::array<int>)</int> 就等于 5 * sizeof(int)。
声明和初始化必须写明大小,且不能推导
这是最容易卡住的地方。下面这些写法都错:
std::array arr = {1, 2, 3}; // ❌ C++17 起仍不支持 CTAD(类模板实参推导)用于 std::array
std::array<int> a = {1, 2, 3}; // ❌ 缺少第二模板参数(元素个数)
std::array<int, 3> a = {1, 2, 3}; // ✅ 正确想省事?用辅助函数 std::to_array(C++20):
auto a = std::to_array({1, 2, 3}); // 推出 std::array<int, 3>访问元素时,operator[] 不检查边界,at() 才会抛异常
这和 std::vector::operator[] 行为一致,但新手常误以为 std::array 更“安全”。其实:
立即学习“C++免费学习笔记(深入)”;
-
a[5]—— 越界,未定义行为,编译器通常不报错 -
a.at(5)—— 抛出std::out_of_range -
a.front()/a.back()—— 同样不检查空数组(但std::array不可能为空,最小 size 是 0,此时调用front仍是未定义)
传参时别直接传 std::array,优先用引用或指针
因为它是值类型,拷贝代价等于整个数组内存(比如 std::array<double></double> 拷贝一次就是 8KB)。常见错误写法:
void func(std::array<int, 5> a) { ... } // ❌ 值传递,不必要拷贝应改为:
-
void func(const std::array<int>& a)</int>—— 最常用 -
void func(std::array<int>* a)</int>—— 少用,除非要修改 - 泛型场景下用模板:
template<size_t n> void func(const std::array<int n>& a)</int></size_t>
注意:不能用 std::array<int></int> 来“泛化大小”,N 必须是编译期常量,每个不同 N 都是独立类型。
真正容易被忽略的是:std::array 的迭代器是原生指针(T*),所以 &a[0] 和 a.data() 等价,能直接传给 C 接口;但它没有 capacity(),也没有 resize()——它就不是用来“变”的,一旦写 std::array,就得接受它的大小钉死在模板参数里。










