std::array必须完整指定元素类型和编译期常量大小,如std::array;不支持运行时大小、不可动态扩容,栈上存储,初始化须用花括号。

std::array 的定义语法和类型参数必须写全
定义 std::array 时不能只写 std::array<int></int>,必须同时指定元素类型和大小,比如 std::array<int></int>。这是编译期确定大小的容器,第二个模板参数是 字面量整数(非类型模板参数),不能是变量或运行时计算值。
常见错误现象:int n = 5; std::array<int n> arr;</int> → 编译失败,报错类似 error: non-type template argument is not a constant expression。
- 正确写法:
std::array<int> arr = {1, 2, 3, 4, 5};</int> - 也可用默认初始化:
std::array<double> vec{};</double>(所有元素零初始化) - 大小为 0 是合法的:
std::array<char> empty;</char>,但empty.data()返回空指针,empty.begin() == empty.end()
访问元素:operator[]、at() 和 data() 的区别
operator[] 不做越界检查,性能等价于原生数组;at() 会抛出 std::out_of_range 异常,适合调试阶段启用;data() 返回指向首元素的原始指针,可用于传给 C 风格 API。
-
arr[10]:若越界,行为未定义(可能崩溃、静默读错内存) -
arr.at(10):立即抛出异常,便于定位问题 -
qsort(arr.data(), arr.size(), sizeof(int), cmp_func);:安全传递给 C 函数 - 注意:
arr.data()在空数组时返回有效但不可解引用的指针,使用前仍需判断arr.empty()
和 C 数组、std::vector 的关键差异点
std::array 是栈上分配、固定大小、无动态内存管理开销的聚合类型;它不拥有堆内存,拷贝是逐元素复制,没有 move 语义优化空间(C++17 起对 trivially copyable 类型,编译器可能优化 memcpy)。
- 对比 C 数组:
sizeof(std::array<int>) == sizeof(int) * 10</int>,且支持拷贝赋值、可作为函数参数按值传递 - 对比
std::vector:没有push_back、resize等接口;size()和max_size()恒等,且为 constexpr - 兼容性注意:在需要
std::span或接受迭代器范围的函数中,arr.begin()/arr.end()可直接使用,但别误用&arr[0]代替arr.data()—— 对空数组前者未定义
初始化陷阱:花括号初始化 vs 圆括号初始化
必须用花括号初始化列表({}),圆括号(())会触发构造函数重载歧义,甚至被解释为函数声明(最令人头疼的“most vexing parse”)。
- 正确:
std::array<int> a = {1, 2, 3};</int>或std::array<int> a{1, 2, 3};</int> - 错误:
std::array<int> a(1, 2, 3);</int>→ 编译失败 - 更隐蔽的错误:
std::array<int> b();</int>→ 这声明了一个返回std::array的函数,不是变量定义 - 如果只初始化部分元素,剩余自动零初始化:
std::array<int> c{1};</int>等价于{1, 0, 0, 0}
真正容易被忽略的是:当把 std::array 作为结构体成员或类成员时,它的默认构造函数不会自动调用元素类型的默认构造(除非显式初始化),尤其当元素是自定义类型且无默认构造函数时,编译会直接报错。这时候得手动在成员初始化列表里写清楚。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











