Wiki
std::array
本文由簡體中文內容確定性轉換,並受版本化術語表保護。
1.本節解決什麼問題
C 風格陣列(int arr[5])有很多缺點:不能直接賦值、傳給函式時會退化成指標丟失大小資訊、沒有邊界檢查。而 std::vector 雖然功能強大,但它是動態分配記憶體的,有微小的額外開銷。
std::array 解決的是:當你需要一個編譯期確定大小、棧上分配的陣列時,提供一個和 C 陣列一樣快、但擁有 STL 容器介面(有 size()、有迭代器、可賦值)的安全陣列。
2.這個特性是什麼
std::array<T, N> 是 STL 中封裝了固定大小陣列的容器模板。它大小在編譯時確定,不動態分配記憶體(在棧上),包裝了 C 陣列同時提供 STL 容器的標準介面。
3.C++ 標準版本
C++11
4.需要的標頭檔案
#include <array>
執行結果: 此程式碼塊不含 main 函式,是語法、介面或分檔案示例,不能獨立執行,因此沒有終端輸出。
5.基本語法
std::array<元素类型, 大小> 变量名; // 默认初始化(值未定义)
std::array<元素类型, 大小> 变量名 = {}; // 全部初始化为零
std::array<元素类型, 大小> 变量名 = {v1, v2, ...}; // 列表初始化
執行結果: 此程式碼塊不含 main 函式,是語法、介面或分檔案示例,不能獨立執行,因此沒有終端輸出。
6.常用用法
| 操作 | 說明 |
|---|---|
a[i] |
隨機訪問(不檢查越界) |
a.at(i) |
隨機訪問(檢查越界) |
a.size() |
返回元素個數(編譯期常量) |
a.empty() |
是否為空(永遠為 false) |
a.front() |
返回第一個元素 |
a.back() |
返回最後一個元素 |
a.fill(val) |
用 val 填充所有元素 |
a.data() |
返回底層 C 陣列指標 |
7.示例程式碼
7.1.示例 1:建立 array 並訪問元素
#include <iostream>
#include <array>
using namespace std;
int main()
{
// 创建一个包含 5 个 int 的 array,并初始化
std::array<int, 5> arr = {10, 20, 30, 40, 50};
// 用下标访问
std::cout << "arr[0] = " << arr[0] << "\n";
std::cout << "arr[4] = " << arr[4] << "\n";
// 用 size() 获取大小
std::cout << "size = " << arr.size() << "\n";
return 0;
}
執行結果:
arr[0] = 10
arr[4] = 50
size = 5
7.2.示例 2:在示例 1 基礎上,用 at() 安全訪問和 fill() 填充
#include <iostream>
#include <array>
using namespace std;
int main()
{
std::array<int, 5> arr = {10, 20, 30, 40, 50};
// 用 at() 安全访问
std::cout << "arr.at(2) = " << arr.at(2) << "\n";
// 用 fill() 将所有元素设为同一个值
arr.fill(99);
std::cout << "after fill: ";
for (int n : arr)
{
std::cout << n << " ";
}
std::cout << "\n";
return 0;
}
執行結果:
arr.at(2) = 30
after fill: 99 99 99 99 99
7.3.示例 3:在示例 2 基礎上,對比 C 陣列和 std::array 傳遞引數
#include <iostream>
#include <array>
using namespace std;
// C 风格:数组退化为指针,丢失大小信息
void print_c_array(int* arr, int size)
{
std::cout << "C array: ";
for (int i = 0; i < size; ++i)
{
std::cout << arr[i] << " ";
}
std::cout << "\n";
}
// std::array:大小信息不丢失
void print_std_array(const std::array<int, 5>& arr)
{
std::cout << "std::array: ";
for (int n : arr)
{
std::cout << n << " ";
}
std::cout << "\n";
std::cout << "size from inside function = " << arr.size() << "\n";
}
int main()
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
// C 风格:需要额外传大小
print_c_array(arr.data(), arr.size());
// std::array:自带大小信息
print_std_array(arr);
return 0;
}
執行結果:
C array: 1 2 3 4 5
std::array: 1 2 3 4 5
size from inside function = 5
8.執行結果
見上方每個示例的"執行結果"。
9.示例中的關鍵語法解釋
| 示例 | 講了什麼 | 新出現的語法 | 為什麼這樣寫 | 注意事項 |
|---|---|---|---|---|
| 示例 1 | 建立 array 和基本訪問 | std::array<T, N>、size() |
array 大小是編譯期常量,size() 返回固定值 |
大小必須是編譯期常量,不能傳變數 |
| 示例 2 | at() 安全訪問和 fill() 填充 | at()、fill() |
at() 越界會拋異常;fill() 方便批次賦值 |
fill() 對所有元素賦相同值 |
| 示例 3 | 對比 C 陣列和 array 傳參 | data()、const std::array<int,5>& |
array 傳參時大小資訊不丟失 | array 大小是型別的一部分,不同大小是不同的型別 |
10.array 和 vector 的區別什麼時候明顯
如果只是存 5 個整數,array 和 vector 看起來都能用。但放到工程裡,差異主要體現在“大小是否固定”和“是否需要動態擴容”:
| 場景 | 推薦 | 原因 |
|---|---|---|
三軸 IMU 資料 {x, y, z} |
std::array<double, 3> |
大小永遠是 3,不需要擴容 |
固定長度 PID 引數 {kp, ki, kd} |
std::array<double, 3> |
編譯期就知道大小,語義明確 |
| 執行時讀取一批感測器點 | std::vector<Point> |
點的數量執行時才知道 |
| 使用者輸入任意數量資料 | std::vector<T> |
需要 push_back 動態增長 |
array 更像“有 STL 介面的固定陣列”,vector 更像“會變長的陣列”。不要因為 array 更輕量就到處用它:只要元素個數執行時才知道,就應該用 vector。
10.1.示例 4:固定三軸資料更適合 array
#include <array>
#include <iostream>
using namespace std;
// std::array 是固定长度数组,长度在编译期就确定。
double norm3(const std::array<double, 3>& v)
{
return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
std::array<double, 3> accel = {0.1, 0.2, 9.8};
std::cout << "accel size = " << accel.size() << "\n";
std::cout << "squared norm = " << norm3(accel) << "\n";
return 0;
}
執行結果:
accel size = 3
squared norm = 96.09
這個例子中,三軸資料必須正好是 3 個值。用 std::array<double, 3> 可以把這個約束寫進型別裡;如果誤傳 std::array<double, 2>,編譯期就會報錯。
11.常見錯誤
錯誤 1:用變數指定 array 大小
int n = 5;
std::array<int, n> arr; // ❌ 编译错误!n 必须是编译期常量
執行結果: 此程式碼塊不含 main 函式,是語法、介面或分檔案示例,不能獨立執行,因此沒有終端輸出。
正確做法:用 constexpr 常量,或者改用 std::vector。
錯誤 2:忘記初始化就訪問
std::array<int, 5> arr; // 值未定义(栈上的垃圾值)
std::cout << arr[0]; // ❌ 未定义行为
執行結果: 此程式碼塊不含 main 函式,是語法、介面或分檔案示例,不能獨立執行,因此沒有終端輸出。
正確做法:用 {} 初始化或 fill()。
錯誤 3:不同大小的 array 互相賦值
std::array<int, 3> a = {1, 2, 3};
std::array<int, 5> b = a; // ❌ 编译错误!类型不同
執行結果: 此程式碼塊不含 main 函式,是語法、介面或分檔案示例,不能獨立執行,因此沒有終端輸出。
正確做法:std::array<int,3> 和 std::array<int,5> 是不同的型別,不能互相賦值。
12.使用建議
- 編譯期確定大小用 array:如果大小在編譯時就已知,用
std::array比std::vector更輕量(無堆分配)。 - 代替 C 陣列:能用
std::array的地方就不要用int arr[N]。 - 傳參注意大小:
std::array<T, N>的大小是型別的一部分,函式簽名要指定 N。 - 可賦值:和 C 陣列不同,
std::array能用=整體賦值(相同型別)。
13.小結
std::array<T, N>封裝了固定大小的陣列,大小在編譯期確定。- 擁有 STL 容器的標準介面(
size()、at()、迭代器等)。 - 可以整體賦值,傳給函式時不會退化為指標,大小資訊不丟失。
- 適用於編譯期已知大小的場景,比
vector更輕量。