C++学习笔记-静态数组(std::array)

std::array是C++11引入的静态数组容器,它结合了C风格数组的性能和STL容器的便利性。相比原始数组,std::array提供了边界检查、迭代器支持和大小信息等功能。

std::array的基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <array>

/* 如果使用C风格数组,就必须传递一个size参数,因为你不知道数组的大小 */
void PrintArray1(int* array, unsigned int size)
{
    for (unsigned int i = 0; i < size; i++)
        std::cout << array[i] << " ";
    std::cout << std::endl;
}

/*
这里Cherno说有个问题,就是签名里要明确数组的大小
虽然可以调用array.size()来获取大小,但这样就冲突了
他的话说是模板,但这个模板实现,我觉得跟普通的函数没什么实质不同,
因为size参数还是外部确定的。
但是实际上要实现的应该是函数内部确定数组大小,而不是外部确定。
我不知道Cherno的标准到底是什么,可能我也理解错了。
*/
template<unsigned int N>
void PrintArray2(const std::array<int, N>& array)
{
    for (unsigned int i = 0; i < N /* array.size() // 也可以用array.size(),但由于大小N已经确定了。*/; i++)
        std::cout << array[i] << " ";
    std::cout << std::endl;
}

int main()
{
    /* C风格数组 */
    int dataOld[5] = {1, 2, 3, 4, 5};
    PrintArray1(dataOld, 5); // C风格的话必须传递size参数

    /* C++标准库提供的静态数组 */
    std::array<int, 5> data = {1, 2, 3, 4, 5};
    PrintArray2(data); // 这里很好,可以不用显示指定模板参数,因为编译器通过函数的参数可以自动推导模板参数,所以不用显示指定。

    // 使用迭代器遍历
    for (auto it = data.begin(); it != data.end(); it++)
        std::cout << *it << " ";
    std::cout << std::endl;

    return 0;
}

std::array与C风格数组的对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <array>

void CompareArrayTypes()
{
    std::cout << "=== Array Types Comparison ===" << std::endl;
    
    // C风格数组
    int cArray[5] = {1, 2, 3, 4, 5};
    
    // std::array
    std::array<int, 5> stdArray = {1, 2, 3, 4, 5};
    
    std::cout << "C-style array:" << std::endl;
    std::cout << "Size: " << sizeof(cArray) / sizeof(int) << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << cArray[i] << " ";
    }
    std::cout << std::endl;
    
    std::cout << "\nstd::array:" << std::endl;
    std::cout << "Size: " << stdArray.size() << std::endl;
    std::cout << "Max size: " << stdArray.max_size() << std::endl;
    std::cout << "Empty: " << (stdArray.empty() ? "Yes" : "No") << std::endl;
    
    for (const auto& element : stdArray)
    {
        std::cout << element << " ";
    }
    std::cout << std::endl;
    
    // std::array的优势
    std::cout << "\nstd::array advantages:" << std::endl;
    std::cout << "First element: " << stdArray.front() << std::endl;
    std::cout << "Last element: " << stdArray.back() << std::endl;
    std::cout << "Element at index 2: " << stdArray.at(2) << std::endl; // 带边界检查
    
    // 边界检查示例
    try
    {
        std::cout << "Accessing out of bounds: " << stdArray.at(10) << std::endl;
    }
    catch (const std::out_of_range& e)
    {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
}

int main()
{
    CompareArrayTypes();
    return 0;
}

std::array的高级功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <array>
#include <algorithm>
#include <numeric>

void AdvancedArrayOperations()
{
    std::cout << "=== Advanced Array Operations ===" << std::endl;
    
    std::array<int, 10> numbers;
    
    // 填充数组
    numbers.fill(42);
    std::cout << "After fill(42): ";
    for (const auto& num : numbers)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 使用iota填充递增序列
    std::iota(numbers.begin(), numbers.end(), 1);
    std::cout << "After iota(1): ";
    for (const auto& num : numbers)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 排序
    std::array<int, 5> unsorted = {5, 2, 8, 1, 9};
    std::cout << "Before sort: ";
    for (const auto& num : unsorted)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    std::sort(unsorted.begin(), unsorted.end());
    std::cout << "After sort: ";
    for (const auto& num : unsorted)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 查找元素
    auto found = std::find(unsorted.begin(), unsorted.end(), 5);
    if (found != unsorted.end())
    {
        std::cout << "Found 5 at position: " << std::distance(unsorted.begin(), found) << std::endl;
    }
    
    // 累加
    int sum = std::accumulate(unsorted.begin(), unsorted.end(), 0);
    std::cout << "Sum of elements: " << sum << std::endl;
    
    // 变换
    std::array<int, 5> squared;
    std::transform(unsorted.begin(), unsorted.end(), squared.begin(),
                   [](int x) { return x * x; });
    
    std::cout << "Squared elements: ";
    for (const auto& num : squared)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

int main()
{
    AdvancedArrayOperations();
    return 0;
}

多维std::array

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <array>

void MultidimensionalArrays()
{
    std::cout << "=== Multidimensional Arrays ===" << std::endl;
    
    // 二维数组
    std::array<std::array<int, 3>, 3> matrix = {{
        {{1, 2, 3}},
        {{4, 5, 6}},
        {{7, 8, 9}}
    }};
    
    std::cout << "2D Array (3x3 matrix):" << std::endl;
    for (size_t i = 0; i < matrix.size(); ++i)
    {
        for (size_t j = 0; j < matrix[i].size(); ++j)
        {
            std::cout << matrix[i][j] << " ";
        }
        std::cout << std::endl;
    }
    
    // 使用范围for循环
    std::cout << "\nUsing range-based for loop:" << std::endl;
    for (const auto& row : matrix)
    {
        for (const auto& element : row)
        {
            std::cout << element << " ";
        }
        std::cout << std::endl;
    }
    
    // 三维数组
    std::array<std::array<std::array<int, 2>, 2>, 2> cube = {{
        {{
            {{1, 2}},
            {{3, 4}}
        }},
        {{
            {{5, 6}},
            {{7, 8}}
        }}
    }};
    
    std::cout << "\n3D Array (2x2x2 cube):" << std::endl;
    for (size_t i = 0; i < cube.size(); ++i)
    {
        std::cout << "Layer " << i << ":" << std::endl;
        for (size_t j = 0; j < cube[i].size(); ++j)
        {
            for (size_t k = 0; k < cube[i][j].size(); ++k)
            {
                std::cout << cube[i][j][k] << " ";
            }
            std::cout << std::endl;
        }
        std::cout << std::endl;
    }
}

int main()
{
    MultidimensionalArrays();
    return 0;
}

std::array的模板应用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <iostream>
#include <array>
#include <string>

// 通用的数组打印函数
template<typename T, size_t N>
void PrintArray(const std::array<T, N>& arr, const std::string& name = "Array")
{
    std::cout << name << " [size=" << N << "]: ";
    for (const auto& element : arr)
    {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

// 数组操作模板
template<typename T, size_t N>
std::array<T, N> MultiplyArray(const std::array<T, N>& arr, T multiplier)
{
    std::array<T, N> result;
    for (size_t i = 0; i < N; ++i)
    {
        result[i] = arr[i] * multiplier;
    }
    return result;
}

// 数组求和模板
template<typename T, size_t N>
T SumArray(const std::array<T, N>& arr)
{
    T sum = T{};  // 零初始化
    for (const auto& element : arr)
    {
        sum += element;
    }
    return sum;
}

// 数组比较模板
template<typename T, size_t N>
bool ArraysEqual(const std::array<T, N>& arr1, const std::array<T, N>& arr2)
{
    for (size_t i = 0; i < N; ++i)
    {
        if (arr1[i] != arr2[i])
            return false;
    }
    return true;
}

void TemplateArrayOperations()
{
    std::cout << "=== Template Array Operations ===" << std::endl;
    
    // 整数数组
    std::array<int, 5> intArray = {1, 2, 3, 4, 5};
    PrintArray(intArray, "Integer Array");
    
    auto doubledInts = MultiplyArray(intArray, 2);
    PrintArray(doubledInts, "Doubled Integers");
    
    int intSum = SumArray(intArray);
    std::cout << "Sum of integers: " << intSum << std::endl;
    
    // 浮点数组
    std::array<double, 4> doubleArray = {1.1, 2.2, 3.3, 4.4};
    PrintArray(doubleArray, "Double Array");
    
    auto scaledDoubles = MultiplyArray(doubleArray, 1.5);
    PrintArray(scaledDoubles, "Scaled Doubles");
    
    double doubleSum = SumArray(doubleArray);
    std::cout << "Sum of doubles: " << doubleSum << std::endl;
    
    // 字符串数组
    std::array<std::string, 3> stringArray = {"Hello", "World", "C++"};
    PrintArray(stringArray, "String Array");
    
    // 数组比较
    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::cout << "arr1 == arr2: " << (ArraysEqual(arr1, arr2) ? "true" : "false") << std::endl;
    std::cout << "arr1 == arr3: " << (ArraysEqual(arr1, arr3) ? "true" : "false") << std::endl;
}

int main()
{
    TemplateArrayOperations();
    return 0;
}

std::array的性能考虑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <array>
#include <vector>
#include <chrono>

void PerformanceComparison()
{
    std::cout << "=== Performance Comparison ===" << std::endl;
    
    const size_t SIZE = 1000000;
    const int ITERATIONS = 100;
    
    // C风格数组性能测试
    auto start = std::chrono::high_resolution_clock::now();
    for (int iter = 0; iter < ITERATIONS; ++iter)
    {
        int* cArray = new int[SIZE];
        for (size_t i = 0; i < SIZE; ++i)
        {
            cArray[i] = i;
        }
        
        volatile int sum = 0;  // 防止编译器优化
        for (size_t i = 0; i < SIZE; ++i)
        {
            sum += cArray[i];
        }
        
        delete[] cArray;
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto cArrayTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // std::vector性能测试
    start = std::chrono::high_resolution_clock::now();
    for (int iter = 0; iter < ITERATIONS; ++iter)
    {
        std::vector<int> vec(SIZE);
        for (size_t i = 0; i < SIZE; ++i)
        {
            vec[i] = i;
        }
        
        volatile int sum = 0;
        for (size_t i = 0; i < SIZE; ++i)
        {
            sum += vec[i];
        }
    }
    end = std::chrono::high_resolution_clock::now();
    auto vectorTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 小型std::array性能测试(栈分配)
    const size_t SMALL_SIZE = 1000;
    start = std::chrono::high_resolution_clock::now();
    for (int iter = 0; iter < ITERATIONS * 1000; ++iter)  // 更多迭代因为数组更小
    {
        std::array<int, SMALL_SIZE> arr;
        for (size_t i = 0; i < SMALL_SIZE; ++i)
        {
            arr[i] = i;
        }
        
        volatile int sum = 0;
        for (size_t i = 0; i < SMALL_SIZE; ++i)
        {
            sum += arr[i];
        }
    }
    end = std::chrono::high_resolution_clock::now();
    auto arrayTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "Performance results (" << ITERATIONS << " iterations):" << std::endl;
    std::cout << "C-style array (heap): " << cArrayTime.count() << " ms" << std::endl;
    std::cout << "std::vector (heap): " << vectorTime.count() << " ms" << std::endl;
    std::cout << "std::array (stack, " << ITERATIONS * 1000 << " iterations): " << arrayTime.count() << " ms" << std::endl;
    
    std::cout << "\nMemory allocation:" << std::endl;
    std::cout << "C-style array: Manual heap allocation" << std::endl;
    std::cout << "std::vector: Automatic heap allocation" << std::endl;
    std::cout << "std::array: Stack allocation (faster)" << std::endl;
}

int main()
{
    PerformanceComparison();
    return 0;
}

实际应用示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <array>
#include <algorithm>
#include <random>

// 游戏中的固定大小数据结构
class GameBoard
{
private:
    static constexpr size_t BOARD_SIZE = 8;
    std::array<std::array<int, BOARD_SIZE>, BOARD_SIZE> m_Board;
    
public:
    GameBoard()
    {
        // 初始化棋盘
        for (auto& row : m_Board)
        {
            row.fill(0);
        }
    }
    
    void SetPiece(size_t row, size_t col, int piece)
    {
        if (row < BOARD_SIZE && col < BOARD_SIZE)
        {
            m_Board[row][col] = piece;
        }
    }
    
    int GetPiece(size_t row, size_t col) const
    {
        if (row < BOARD_SIZE && col < BOARD_SIZE)
        {
            return m_Board[row][col];
        }
        return -1;  // 无效位置
    }
    
    void Print() const
    {
        std::cout << "Game Board:" << std::endl;
        for (const auto& row : m_Board)
        {
            for (int piece : row)
            {
                std::cout << piece << " ";
            }
            std::cout << std::endl;
        }
    }
    
    constexpr size_t GetSize() const { return BOARD_SIZE; }
};

// 数学向量类
template<typename T, size_t N>
class Vector
{
private:
    std::array<T, N> m_Data;
    
public:
    Vector() { m_Data.fill(T{}); }
    
    Vector(std::initializer_list<T> init)
    {
        size_t i = 0;
        for (const auto& value : init)
        {
            if (i < N) m_Data[i++] = value;
        }
        while (i < N) m_Data[i++] = T{};
    }
    
    T& operator[](size_t index) { return m_Data[index]; }
    const T& operator[](size_t index) const { return m_Data[index]; }
    
    Vector operator+(const Vector& other) const
    {
        Vector result;
        for (size_t i = 0; i < N; ++i)
        {
            result[i] = m_Data[i] + other[i];
        }
        return result;
    }
    
    Vector operator*(T scalar) const
    {
        Vector result;
        for (size_t i = 0; i < N; ++i)
        {
            result[i] = m_Data[i] * scalar;
        }
        return result;
    }
    
    T Dot(const Vector& other) const
    {
        T result = T{};
        for (size_t i = 0; i < N; ++i)
        {
            result += m_Data[i] * other[i];
        }
        return result;
    }
    
    void Print() const
    {
        std::cout << "(";
        for (size_t i = 0; i < N; ++i)
        {
            std::cout << m_Data[i];
            if (i < N - 1) std::cout << ", ";
        }
        std::cout << ")" << std::endl;
    }
    
    constexpr size_t Size() const { return N; }
};

using Vector3f = Vector<float, 3>;
using Vector2i = Vector<int, 2>;

int main()
{
    std::cout << "=== Practical Applications ===" << std::endl;
    
    // 游戏棋盘示例
    GameBoard board;
    board.SetPiece(0, 0, 1);
    board.SetPiece(1, 1, 2);
    board.SetPiece(2, 2, 1);
    board.Print();
    
    // 数学向量示例
    Vector3f v1{1.0f, 2.0f, 3.0f};
    Vector3f v2{4.0f, 5.0f, 6.0f};
    
    std::cout << "\nVector operations:" << std::endl;
    std::cout << "v1: "; v1.Print();
    std::cout << "v2: "; v2.Print();
    
    auto sum = v1 + v2;
    std::cout << "v1 + v2: "; sum.Print();
    
    auto scaled = v1 * 2.0f;
    std::cout << "v1 * 2: "; scaled.Print();
    
    float dot = v1.Dot(v2);
    std::cout << "v1 · v2 = " << dot << std::endl;
    
    return 0;
}

总结

  1. std::array特点
    • 固定大小的栈分配数组
    • 提供STL容器的接口和功能
    • 零开销抽象,性能与C风格数组相当
  2. 优势
    • 边界检查(at()方法)
    • 大小信息(size()方法)
    • 迭代器支持
    • STL算法兼容
  3. 使用场景
    • 已知固定大小的数据集合
    • 需要栈分配的高性能场景
    • 替代C风格数组的现代化选择
  4. Cherno推荐:总是使用std::array而不是原始C风格数组
  5. 注意事项:大型数组可能导致栈溢出,此时应考虑使用std::vector
updatedupdated2025-09-202025-09-20