第 16.2 節

std::array

0瀏覽次數0訪問次數--跳出率--平均停留

What problem does this section solve?

C-style arrays (int arr[5]) have many drawbacks: they cannot be assigned directly, they decay into pointers when passed to functions (losing size information), and there is no bounds checking. Dynamic allocation (std::vector), however, is powerful but involves dynamically allocating memory, which comes with a small overhead.

std::array addresses the need for a compile-time sized, stack-allocated array that offers the same performance as a C array but with an STL container interface (including size(), iterators, and assignability), providing a safe alternative.

What is this feature?

std::array<T, N> is a container template in the STL that encapsulates a fixed-size array. Its size is determined at compile time and does not dynamically allocate memory (it resides on the stack), wrapping a C array while providing the standard interface of an STL container.

C++ standard version

C++11

Required header files

#include <array>

Running/Observing Results: This is a syntax or interface example, focus on the writing style; run and verify after incorporating it into a complete program.

Basic Syntax

std::array<元素类型, 大小> 变量名;            // 默认初始化(值未定义)
std::array<元素类型, 大小> 变量名 = {};        // 全部初始化为零
std::array<元素类型, 大小> 变量名 = {v1, v2, ...}; // 列表初始化

Run/Observation Results: This is a syntax fragment, focus on the writing style; run it after completing the context.

Common Usage

OperationExplanation
a[i]Random access (without bounds checking)
a.at(i)random access (with bounds checking)
a.size()Return element count (compile-time constant)
a.empty()Whether it is empty (always false)
a.front()Return the first element.
a.back()Return the last element
a.fill(val)Fill all elements with val
a.data()Return pointer to underlying C array

Example code

Example 1: Create an array and access elements

#include <iostream>
#include <array>

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;
}

Results

arr[0] = 10
arr[4] = 50
size = 5

Example 2: Based on Example 1, using at() for safe access and fill() for filling

#include <iostream>
#include <array>

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;
}

Results

arr.at(2) = 30
after fill: 99 99 99 99 99 

Example 3: Building on Example 2, comparing C arrays and std::array parameter passing

#include <iostream>
#include <array>

// 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;
}

Results

C array: 1 2 3 4 5 
std::array: 1 2 3 4 5 
size from inside function = 5

runtime results

See the "running results" for each example above.

Key syntax explanation in the example

|Here is the translation of the provided Simplified Chinese Markdown fragment into natural American English, following all specified rules.


ExampleDiscusses whatNewly emerged syntaxWhy write it this wayPrecautions
Example 1Create array and basic accessstd::array<T, N>size()The array size is a compile-time constant, size() returns a fixed value.The size must be a compile-time constant; variables cannot be passed.
Example 2at() safe access and fill() fillingat()fill()at() throws an exception when out of bounds; fill() convenient for batch assignment.fill() Assign the same value to all elements
Example 3Comparing C arrays and array parameter passingdata()const std::array<int,5>&Size information is not lost when passing arrays as parameters.The size of an array is part of its type, and different sizes are different types.

The differences between array and vector become most evident in the following scenarios:

  • When fixed-size storage is needed: If you know the exact number of elements at compile time and this size won't change, array is more efficient.
  • When dynamic resizing is required: If the number of elements may change during runtime, vector is the clear choice.
  • In performance-sensitive contexts: array avoids the overhead of heap allocation and dynamic resizing, making it faster in tight loops or embedded systems.
  • When passing data to low-level APIs: array provides a contiguous, fixed-size block of memory that aligns well with C-style functions.

If just storing 5 integers, array and vector seem to both work. However, within a project, the differences mainly lie in "whether the size is fixed" and "whether dynamic expansion is needed":

SceneRecommendationReason
Three-axis IMU data {x, y, z}std::array<double, 3>The size is always 3, no expansion needed.
Fixed-length PID parameters {kp, ki, kd}std::array<double, 3>The size is known at compile time, with clear semantics.
Reading a batch of sensor data at runtime.std::vector<Point>The number of points is only known at runtime.
User inputs any amount of data.std::vector<T>require dynamic growth for push_back

array is more like "a fixed-size array with an STL interface," while vector is more like "a resizable array." Don't use array everywhere just because it's more lightweight: whenever the number of elements isn't known until runtime, you should use vector.

Example 4: Fixed three-axis data is better suited for array.

#include <array>
#include <iostream>

// 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;
}

Results

accel size = 3
squared norm = 96.09

In this example, the three-axis data must be exactly 3 values. Using std::array<double, 3> allows this constraint to be written into the type; if std::array<double, 2> is mistakenly passed, it will result in a compile-time error.

Common Errors

Error 1: Specifying array size with a variable

int n = 5;
std::array<int, n> arr;  // ❌ 编译错误!n 必须是编译期常量

Running/Observing Results: This is a syntax or interface example, focus on the writing style; run and verify after incorporating it into a complete program.

The correct approach: use the constexpr constant, or alternatively switch to std::vector.

Error 2: Accessing before initialization

std::array<int, 5> arr;   // 值未定义(栈上的垃圾值)
std::cout << arr[0];      // ❌ 未定义行为

Running/Observation Results: After running, the corresponding content will be printed according to the output statements. The variable values can be inferred based on the order of initialization, assignment, and function calls.

Correct approach: Initialize with {} or use fill().

Error 3: Assigning between arrays of different sizes

std::array<int, 3> a = {1, 2, 3};
std::array<int, 5> b = a;  // ❌ 编译错误!类型不同

Running/Observing Results: This is a syntax or interface example, focus on the writing style; run and verify after incorporating it into a complete program.

The correct approach: std::array<int,3> and std::array<int,5> are of different types and cannot be assigned to each other.

使用建议

  • 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
  • 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
  • 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
  • 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
  • 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。

如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。

  1. For sizes known at compile time, use an array:If the size is known at compile time, using std::array is more lightweight than std::vector (without heap allocation).
  2. Replacing C Arrays: Use std::array whenever int arr[N] can be used.
  3. Note the size when passing arguments: The size of std::array<T, N> is part of its type, and the function signature must specify N.
  4. Assignable: Unlike C arrays, std::array can be assigned as a whole using = (of the same type).

Summary

  • std::array<T, N> encapsulates a fixed-size array, with its size determined at compile time.
  • Includes the standard interface of STL containers (size(), at(), iterators, etc.).
  • Yes, you can assign the entire array, and when passing it to a function, it won’t decay into a pointer, so the size information is retained.
  • Suitable for scenarios where the size is known at compile time, more lightweight than vector.
音乐页