C++标准模板库(STL)array固定容器
std::array 是 C++11 引入的固定大小数组容器,替代传统 C 风格数组,兼具静态数组的性能和容器的便捷性(如迭代器、边界检查、成员函数)。它的大小在编译期确定,存储在栈上(相比 std::vector 更高效),且支持所有容器通用操作。
std::array 是 C++ 静态数组的最佳替代方案,核心优势:
1. 固定大小(编译期确定),栈存储,效率与原生数组一致;
2. 提供容器化接口(迭代器、成员函数),兼容 STL 算法;
3. 支持安全的边界检查(at())和编译期检查(std::get<I>);
4. 无额外内存开销(相比 vector 无动态分配)。
一、基础初始化与构造
std::array 支持多种初始化方式,核心特点是**大小必须是编译期常量**。
功能1:默认构造(空/零初始化)
- 语法:std::array<T, N> arr;
- 说明:
- 若 T 是内置类型(int/float 等),默认值为零初始化(C++11 起);
- 若 T 是自定义类型,调用默认构造函数。
示例:
#include <iostream>
#include <array>
int main() {
// 默认构造:int 类型零初始化,所有元素为 0
std::array<int, 5> arr1;
std::cout << "默认构造的数组:";
for (int num : arr1) {
std::cout << num << " "; // 输出:0 0 0 0 0
}
std::cout << "\n";
// 自定义类型默认构造
struct Person {
std::string name;
int age = 18; // 类内初始值
};
std::array<Person, 2> arr2;
std::cout << "自定义类型默认构造:"
<< arr2[0].name << "(" << arr2[0].age << "), "
<< arr2[1].name << "(" << arr2[1].age << ")\n";
// 输出:(18), (18)
return 0;
}功能2:聚合初始化(列表初始化)
- 语法:std::array<T, N> arr = {v1, v2, ..., vn};
- 说明:
- 初始化列表元素个数可少于 N,剩余元素零初始化;
- 个数不能超过 N(编译错误)。
示例:
#include <iostream>
#include <array>
int main() {
// 完整初始化
std::array<int, 3> arr1 = {10, 20, 30};
std::cout << "完整初始化:";
for (int num : arr1) std::cout << num << " "; // 10 20 30
std::cout << "\n";
// 部分初始化(剩余元素零初始化)
std::array<double, 4> arr2 = {3.14, 2.718};
std::cout << "部分初始化:";
for (double num : arr2) std::cout << num << " "; // 3.14 2.718 0 0
std::cout << "\n";
// 直接列表初始化(省略 =)
std::array<std::string, 2> arr3{"hello", "world"};
std::cout << "字符串数组:" << arr3[0] << " " << arr3[1] << "\n"; // hello world
return 0;
}功能3:拷贝构造/赋值
- 语法:
- 拷贝构造:std::array<T, N> arr2(arr1); 或 std::array<T, N> arr2 = arr1;
- 拷贝赋值:arr2 = arr1;
- 说明:要求两个 array 的类型(T)和大小(N)完全一致。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 3> arr1 = {1, 2, 3};
// 拷贝构造
std::array<int, 3> arr2(arr1);
std::cout << "拷贝构造:";
for (int num : arr2) std::cout << num << " "; // 1 2 3
std::cout << "\n";
// 拷贝赋值
std::array<int, 3> arr3;
arr3 = arr1;
std::cout << "拷贝赋值:";
for (int num : arr3) std::cout << num << " "; // 1 2 3
std::cout << "\n";
return 0;
}二、元素访问
std::array 提供多种安全/非安全的元素访问方式。
功能1:operator[](非安全访问)
- 语法:arr[index]
- 说明:
- 无边界检查,越界行为未定义(可能崩溃);
- 返回元素的引用,可读写。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 4> arr = {10, 20, 30, 40};
// 读元素
std::cout << "arr[2] = " << arr[2] << "\n"; // 30
// 写元素
arr[1] = 200;
std::cout << "修改后 arr[1] = " << arr[1] << "\n"; // 200
// 越界(未定义行为,可能崩溃)
// std::cout << arr[10] << "\n";
return 0;
}功能2:at()(安全访问)
- 语法:arr.at(index)
- 说明:
- 有边界检查,越界抛出 std::out_of_range 异常;
- 返回元素的引用,可读写。
示例:
#include <iostream>
#include <array>
#include <stdexcept> // 异常头文件
int main() {
std::array<int, 4> arr = {10, 20, 30, 40};
try {
// 安全读
std::cout << "arr.at(3) = " << arr.at(3) << "\n"; // 40
// 安全写
arr.at(0) = 100;
std::cout << "修改后 arr.at(0) = " << arr.at(0) << "\n"; // 100
// 越界,抛出异常
std::cout << arr.at(10) << "\n";
} catch (const std::out_of_range& e) {
std::cerr << "异常:" << e.what() << "\n"; // 输出:array::at: __n (which is 10) >= _Nm (which is 4)
}
return 0;
}功能3:front()(访问第一个元素)
- 语法:arr.front()
- 说明:返回第一个元素的引用,无边界检查(空数组未定义)。
示例:
#include <iostream>
#include <array>
int main() {
std::array<std::string, 3> arr = {"apple", "banana", "cherry"};
// 读第一个元素
std::cout << "第一个元素:" << arr.front() << "\n"; // apple
// 写第一个元素
arr.front() = "orange";
std::cout << "修改后第一个元素:" << arr.front() << "\n"; // orange
return 0;
}功能4:back()(访问最后一个元素)
- 语法:arr.back()
- 说明:返回最后一个元素的引用,无边界检查(空数组未定义)。
示例:
#include <iostream>
#include <array>
int main() {
std::array<double, 3> arr = {1.1, 2.2, 3.3};
// 读最后一个元素
std::cout << "最后一个元素:" << arr.back() << "\n"; // 3.3
// 写最后一个元素
arr.back() = 9.9;
std::cout << "修改后最后一个元素:" << arr.back() << "\n"; // 9.9
return 0;
}功能5:data()(获取底层数组指针)
- 语法:arr.data()
- 说明:返回指向第一个元素的原生指针,可用于兼容 C 风格接口。
示例:
#include <iostream>
#include <array>
#include <cstring> // memcpy 头文件
int main() {
std::array<int, 4> arr = {1, 2, 3, 4};
// 获取原生指针
int* ptr = arr.data();
std::cout << "通过指针访问:";
for (int i = 0; i < 4; ++i) {
std::cout << ptr[i] << " "; // 1 2 3 4
}
std::cout << "\n";
// 兼容 C 函数(如 memcpy)
int buf[4];
memcpy(buf, arr.data(), sizeof(arr));
std::cout << "memcpy 后:";
for (int num : buf) std::cout << num << " "; // 1 2 3 4
std::cout << "\n";
return 0;
}三、容量与状态查询
功能1:size()(获取元素个数)
- 语法:arr.size()
- 说明:返回编译期常量(constexpr),等于数组的固定大小 N。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 5> arr1;
std::array<std::string, 0> arr2; // 空数组
std::cout << "arr1 大小:" << arr1.size() << "\n"; // 5
std::cout << "arr2 大小:" << arr2.size() << "\n"; // 0
// 编译期验证(constexpr 特性)
static_assert(arr1.size() == 5, "arr1 大小必须为5");
return 0;
}功能2:max_size()(获取最大容量)
- 语法:arr.max_size()
- 说明:
- 对于 std::array,max_size() 等于 size()(固定大小);
- 与 vector 的 max_size() 区分(vector 是理论最大容量)。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 7> arr;
std::cout << "size = " << arr.size() << "\n"; // 7
std::cout << "max_size = " << arr.max_size() << "\n"; // 7
return 0;
}功能3:empty()(判断是否为空)
- 语法:arr.empty()
- 说明:
- 返回 bool,仅当 size() == 0 时为 true;
- 编译期常量(constexpr)。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 0> empty_arr;
std::array<int, 3> non_empty_arr;
std::cout << "空数组 empty():" << std::boolalpha << empty_arr.empty() << "\n"; // true
std::cout << "非空数组 empty():" << non_empty_arr.empty() << "\n"; // false
// 编译期判断
static_assert(empty_arr.empty(), "空数组必须返回 true");
return 0;
}四、修改操作
功能1:fill()(填充所有元素)
- 语法:arr.fill(value)
- 说明:将数组所有元素赋值为 value,覆盖原有值。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 4> arr;
// 填充所有元素为 9
arr.fill(9);
std::cout << "填充后:";
for (int num : arr) std::cout << num << " "; // 9 9 9 9
std::cout << "\n";
// 填充自定义类型
std::array<std::string, 2> str_arr;
str_arr.fill("hello");
std::cout << "字符串填充:" << str_arr[0] << " " << str_arr[1] << "\n"; // hello hello
return 0;
}功能2:swap()(交换两个数组)
- 语法:arr1.swap(arr2) 或 std::swap(arr1, arr2)
- 说明:
- 两个数组的类型(T)和大小(N)必须完全一致;
- 交换是 O(1) 操作(仅交换底层指针,无元素拷贝)。
示例:
#include <iostream>
#include <array>
#include <algorithm> // std::swap 头文件
int main() {
std::array<int, 3> arr1 = {1, 2, 3};
std::array<int, 3> arr2 = {10, 20, 30};
// 方法1:成员函数 swap
arr1.swap(arr2);
std::cout << "arr1 交换后:";
for (int num : arr1) std::cout << num << " "; // 10 20 30
std::cout << "\n";
std::cout << "arr2 交换后:";
for (int num : arr2) std::cout << num << " "; // 1 2 3
std::cout << "\n";
// 方法2:std::swap
std::swap(arr1, arr2);
std::cout << "再次交换后 arr1:";
for (int num : arr1) std::cout << num << " "; // 1 2 3
std::cout << "\n";
return 0;
}五、迭代器支持
std::array 提供完整的迭代器接口,兼容 STL 算法。
功能1:begin()/end()(普通迭代器)
- 语法:
- arr.begin():返回指向第一个元素的迭代器;
- arr.end():返回指向最后一个元素**下一个位置**的迭代器(尾后迭代器)。
- 说明:迭代器可读写,支持遍历、算法操作。
示例:
#include <iostream>
#include <array>
#include <algorithm> // std::sort
int main() {
std::array<int, 5> arr = {5, 2, 8, 1, 9};
// 迭代器遍历
std::cout << "迭代器遍历:";
for (auto it = arr.begin(); it != arr.end(); ++it) {
std::cout << *it << " "; // 5 2 8 1 9
}
std::cout << "\n";
// 配合 STL 算法排序
std::sort(arr.begin(), arr.end());
std::cout << "排序后:";
for (auto num : arr) std::cout << num << " "; // 1 2 5 8 9
std::cout << "\n";
return 0;
}功能2:cbegin()/cend()(常量迭代器)
- 语法:
- arr.cbegin():返回指向第一个元素的常量迭代器;
- arr.cend():返回尾后常量迭代器。
- 说明:迭代器只读,不可修改元素,适合 const 场景。
示例:
#include <iostream>
#include <array>
// 常量数组参数,只能用 const 迭代器
void print_const_array(const std::array<int, 4>& arr) {
std::cout << "常量迭代器遍历:";
for (auto it = arr.cbegin(); it != arr.cend(); ++it) {
// *it = 100; // 编译错误:常量迭代器不可写
std::cout << *it << " ";
}
std::cout << "\n";
}
int main() {
std::array<int, 4> arr = {10, 20, 30, 40};
print_const_array(arr); // 10 20 30 40
return 0;
}功能3:rbegin()/rend()(反向迭代器)
- 语法:
- arr.rbegin():返回指向最后一个元素的反向迭代器;
- arr.rend():返回指向第一个元素**前一个位置**的反向尾后迭代器。
- 说明:反向遍历数组(从后往前)。
示例:
#include <iostream>
#include <array>
int main() {
std::array<std::string, 3> arr = {"a", "b", "c"};
// 反向迭代器遍历
std::cout << "反向遍历:";
for (auto it = arr.rbegin(); it != arr.rend(); ++it) {
std::cout << *it << " "; // c b a
}
std::cout << "\n";
return 0;
}功能4:crbegin()/crend()(常量反向迭代器)
- 语法:
- arr.crbegin():返回指向最后一个元素的常量反向迭代器;
- arr.crend():返回反向尾后常量迭代器。
- 说明:只读的反向遍历。
示例:
#include <iostream>
#include <array>
int main() {
const std::array<int, 4> arr = {1, 2, 3, 4}; // 常量数组
// 常量反向迭代器遍历
std::cout << "常量反向遍历:";
for (auto it = arr.crbegin(); it != arr.crend(); ++it) {
std::cout << *it << " "; // 4 3 2 1
}
std::cout << "\n";
return 0;
}六、非成员函数
功能1:std::get<I>()(编译期索引访问)
- 语法:std::get<I>(arr)
- 说明:
- I 是编译期常量(模板参数),越界会编译错误;
- 返回第 I 个元素的引用,可读写。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 3> arr = {10, 20, 30};
// 读元素(I=1)
std::cout << "std::get<1>(arr) = " << std::get<1>(arr) << "\n"; // 20
// 写元素
std::get<0>(arr) = 100;
std::cout << "修改后 get<0> = " << std::get<0>(arr) << "\n"; // 100
// 越界(编译错误)
// std::get<5>(arr);
return 0;
}功能2:std::swap()(全局交换)
- 语法:std::swap(arr1, arr2)
- 说明:等价于成员函数 swap(),是对 std::array 的特化版本,效率更高。
示例:
#include <iostream>
#include <array>
#include <algorithm> // std::swap
int main() {
std::array<double, 2> arr1 = {1.1, 2.2};
std::array<double, 2> arr2 = {9.9, 8.8};
std::swap(arr1, arr2);
std::cout << "arr1: " << arr1[0] << " " << arr1[1] << "\n"; // 9.9 8.8
std::cout << "arr2: " << arr2[0] << " " << arr2[1] << "\n"; // 1.1 2.2
return 0;
}功能3:比较运算符(==/!=/</<=/>/>=)
- 语法:arr1 == arr2、arr1 < arr2 等
- 说明:
- 逐元素比较,要求两个数组大小和类型一致;
- ==:所有元素相等则返回 true;
- 关系运算符(</>)按字典序比较。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 3> arr1 = {1, 2, 3};
std::array<int, 3> arr2 = {1, 2, 3};
std::array<int, 3> arr3 = {1, 2, 4};
std::array<int, 3> arr4 = {0, 9, 9};
std::cout << "arr1 == arr2: " << std::boolalpha << (arr1 == arr2) << "\n"; // true
std::cout << "arr1 == arr3: " << (arr1 == arr3) << "\n"; // false
std::cout << "arr1 < arr3: " << (arr1 < arr3) << "\n"; // true(前两个元素相等,第三个 3<4)
std::cout << "arr1 > arr4: " << (arr1 > arr4) << "\n"; // true(第一个元素 1>0)
return 0;
}七、扩展特性(C++17 及以上)
功能:std::array 的结构化绑定
- 语法:auto [a, b, c] = arr;
- 说明:C++17 引入,可直接解构数组元素,需元素个数匹配。
示例:
#include <iostream>
#include <array>
int main() {
std::array<int, 3> arr = {10, 20, 30};
// 结构化绑定
auto [x, y, z] = arr;
std::cout << "x = " << x << ", y = " << y << ", z = " << z << "\n"; // 10 20 30
// 绑定引用(可修改)
auto& [rx, ry, rz] = arr;
rx = 100;
std::cout << "修改后 arr[0] = " << arr[0] << "\n"; // 100
return 0;
} C++编程语言基础
- C++:从入门到工作的教程
- 这是我的第一个 C++程序!
- C++中main函数有什么作用?
- C++中 #include 指令的作用
- C++中常用的预处理指令
- C++中 iostream 头文件定义了什么
- C++名称空间(namespace)
- C++标准库中 std 命名空间定义了些什么
- C++常用的头文件
- C++源代码的发布方式
- C++变量名的定义、变量的作用、使用规范
- C++的关键字列表
- C++数据类型:整型(整数类型)
- 二进制补码、原码、反码
- C++数据类型:char字符型(整数类型)
- ASCII码表及C++字符函数库(cctype)
- 计算机汉字编码
- C++数据类型:bool类型(整数类型)
- C++中 const 限定符
- C++数据类型:浮点数
- C++运算符:算术运算符
- C++运算符:类型转换规则
- 计算机数据存储大小端模式
- C++运算符:位运算 与 bitset类库
- C++运算符:关系运算符与逻辑运算符
- C++流程控制:顺序、选择、循环、跳转语句
- C++函数的定义、参数传递、重载、嵌套
- C++数组:一维、二维、多维数组的运用
- C-style字符串、库函数 与 std::string对象
- C++数据类型:结构体(struct)
- C++数据类型:联合体(union)
- C++数据类型:枚举(enum)
- C++数据类型别名:typedef
- C++指针
- C++内存操作符:new分配 与 delete释放
- C++标准模板库(STL)容器、算法、迭代器
- C++标准模板库(STL)vector顺序容器
- C++标准模板库(STL)array固定容器
- C++标准模板库(STL)list双向链表容器
- C++标准模板库(STL)deque双端队列
- C++标准模板库(STL)集合 set 关联容器
- C++标准模板库(STL)map关联容器
- C++标准模板库(STL)unordered_set
- C++标准模板库(STL)unordered_map
- C++标准模板库(STL)algorithm算法库
- C++文件操作
- C++数学库(cmath)数学常量与数学函数
- C++模板:函数模板、类模板
- C++与SQLite3联合打造实用的应用程序
- C++实战开发中常用的库(概述)
- 第二部分:C++面向对象编程
- C++:类的定义与声明、类对象应用
- 第三部分:数据结构与算法(概述)
- 第一部分:C++语言简介与学习路线
