跳到正文

Wiki

std::array

約 5 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

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 個整數,arrayvector 看起來都能用。但放到工程裏,差異主要體現在“大小是否固定”和“是否需要動態擴容”:

場景 推薦 原因
三軸 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.使用建議

  1. 編譯期確定大小用 array:如果大小在編譯時就已知,用 std::arraystd::vector 更輕量(無堆分配)。
  2. 代替 C 數組:能用 std::array 的地方就不要用 int arr[N]
  3. 傳參注意大小std::array<T, N> 的大小是類型的一部分,函數簽名要指定 N。
  4. 可賦值:和 C 數組不同,std::array 能用 = 整體賦值(相同類型)。

13.小結

  • std::array<T, N> 封裝了固定大小的數組,大小在編譯期確定。
  • 擁有 STL 容器的標準接口(size()at()、迭代器等)。
  • 可以整體賦值,傳給函數時不會退化為指針,大小信息不丟失。
  • 適用於編譯期已知大小的場景,比 vector 更輕量。