C++28 STL容器--array

std::array 核心定位

std::array 是 C++11 引入的静态数组封装 ,本质是对 C 风格静态数组(如 int arr[5])的 "现代化升级",核心目标:

  • 保留 C 数组 "栈上分配、高效访问" 的优点;
  • 弥补 C 数组 "类型不安全、无边界检查、无容器接口" 的缺陷;
  • 大小编译期固定,无堆内存开销,无需手动管理内存。

核心用法

1. 基本定义与初始化
复制代码
#include <array>   // 必须包含头文件
#include <iostream>

int main() {
    // 方式1:默认初始化(内置类型为随机值,类类型调用默认构造)
    std::array<int, 5> arr1;

    // 方式2:聚合初始化(类似C数组,推荐)
    std::array<int, 5> arr2 = {1, 2, 3, 4, 5}; 
    std::array<int, 5> arr3{1, 2, 3, 4, 5};     // C++11起支持列表初始化

    // 方式3:部分初始化(未初始化的元素补0)
    std::array<int, 5> arr4 = {1, 2}; // 结果:[1,2,0,0,0]

    // 方式4:填充初始化(所有元素设为同一值)
    std::array<int, 5> arr5;
    arr5.fill(8); // 结果:[8,8,8,8,8]

    return 0;
}
2. 元素访问(4 种方式)
复制代码
std::array<int, 5> arr = {1, 2, 3, 4, 5};

// 方式1:operator[](无边界检查,高效,推荐常规场景)
std::cout << arr[2] << std::endl; // 输出3

// 方式2:at()(带边界检查,越界抛异常,调试/安全场景)
try {
    std::cout << arr.at(10) << std::endl; // 越界,抛std::out_of_range
} catch (const std::out_of_range& e) {
    std::cerr << e.what() << std::endl;
}

// 方式3:front()/back()(首尾元素,N=0时调用未定义)
std::cout << arr.front() << std::endl; // 输出1
std::cout << arr.back() << std::endl;  // 输出5

// 方式4:data()(获取原始指针,兼容C风格接口)
int* ptr = arr.data();
std::cout << ptr[3] << std::endl; // 输出4
3. 容量与迭代器
复制代码
std::array<int, 5> arr = {1, 2, 3, 4, 5};

// 容量(编译期固定,无扩容)
std::cout << arr.size() << std::endl;    // 输出5(constexpr,编译期确定)
std::cout << arr.max_size() << std::endl;// 输出5(和size()相等)
std::cout << arr.empty() << std::endl;   // 输出false(N=0时为true)

// 迭代器(支持范围for、算法库)
for (auto it = arr.begin(); it != arr.end(); ++it) {
    std::cout << *it << " "; // 输出1 2 3 4 5
}

// 反向迭代器
for (auto it = arr.rbegin(); it != arr.rend(); ++it) {
    std::cout << *it << " "; // 输出5 4 3 2 1
}

// 范围for循环(简洁)
for (int num : arr) {
    std::cout << num << " ";
}
4. 其他常用操作
复制代码
std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
std::array<int, 5> arr2 = {6, 7, 8, 9, 10};

// 交换两个array(要求大小相同)
arr1.swap(arr2); // arr1变为[6,7,8,9,10],arr2变为[1,2,3,4,5]

// 排序(结合算法库)
#include <algorithm>
std::array<int, 5> arr3 = {5, 3, 1, 4, 2};
std::sort(arr3.begin(), arr3.end()); // 结果:[1,2,3,4,5]

关键特性(核心设计逻辑)

  1. 内存分配:栈上分配,无堆内存开销,析构时无需释放内存,效率和 C 数组一致;
  2. 大小固定 :模板参数 N 是编译期常量,无法动态扩容 / 缩容(无 reserve()/resize() 接口);
  3. 类型安全:模板绑定元素类型和大小,避免 C 数组 "数组名隐式转指针" 导致的类型丢失;
  4. 边界检查at() 提供运行时边界检查,operator[] 无检查(兼顾效率);
  5. 兼容 STL :支持迭代器、算法库(sort/find等),可无缝融入 STL 容器体系;
  6. 空数组特化 :当 N=0 时,std::array<T,0> 仍合法(迭代器返回空指针,size()=0)。

总结

  1. std::array 是 C 静态数组的现代化封装,栈上存储、大小固定、高效且类型安全;
  2. 核心优势:兼顾 C 数组的效率 + STL 容器的易用性,支持边界检查和算法库;
  3. 最佳场景:固定大小、栈上存储、需兼容 STL 的数组场景,替代 C 风格数组优先选它。

自己实现的源码

复制代码
#include <cstddef>   // size_t
#include <iterator>  // 迭代器相关
#include <stdexcept> // 异常(边界检查)

namespace std {
// 模板参数:T是元素类型,N是数组大小(编译期常量)
template <typename T, size_t N>
class array {
public:
    // ========== 类型别名(容器通用接口) ==========
    using value_type             = T;
    using pointer                = T*;
    using const_pointer          = const T*;
    using reference              = T&;
    using const_reference        = const T&;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = T*;         // 迭代器直接用原生指针(随机访问迭代器)
    using const_iterator         = const T*;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // ========== 核心成员:底层静态数组(私有) ==========
    // 直接存储元素,无额外封装(栈上分配,大小N)
    T _M_elems[N];

    // ========== 迭代器接口 ==========
    iterator begin() noexcept { return _M_elems; }
    const_iterator begin() const noexcept { return _M_elems; }
    iterator end() noexcept { return _M_elems + N; }
    const_iterator end() const noexcept { return _M_elems + N; }

    reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
    const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
    reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
    const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }

    // ========== 元素访问 ==========
    // 普通访问(无边界检查,高效)
    reference operator[](size_type i) noexcept { return _M_elems[i]; }
    const_reference operator[](size_type i) const noexcept { return _M_elems[i]; }

    // 带边界检查的访问(调试/安全场景,越界抛异常)
    reference at(size_type i) {
        if (i >= N) {
            throw std::out_of_range("array::at: index out of bounds");
        }
        return _M_elems[i];
    }
    const_reference at(size_type i) const {
        if (i >= N) {
            throw std::out_of_range("array::at: index out of bounds");
        }
        return _M_elems[i];
    }

    // 首/尾元素访问
    reference front() noexcept { return _M_elems[0]; }
    const_reference front() const noexcept { return _M_elems[0]; }
    reference back() noexcept { return _M_elems[N - 1]; }
    const_reference back() const noexcept { return _M_elems[N - 1]; }

    // 获取原始指针(兼容C风格数组)
    pointer data() noexcept { return _M_elems; }
    const_pointer data() const noexcept { return _M_elems; }

    // ========== 容量接口 ==========
    // 大小固定,size()返回编译期常量N
    constexpr size_type size() const noexcept { return N; }
    // 最大容量等于size(无扩容)
    constexpr size_type max_size() const noexcept { return N; }
    // 仅当N=0时为空
    constexpr bool empty() const noexcept { return N == 0; }

    // ========== 操作接口 ==========
    // 填充所有元素为指定值
    void fill(const T& value) {
        for (size_type i = 0; i < N; ++i) {
            _M_elems[i] = value;
        }
    }

    // 交换两个array(要求大小相同)
    void swap(array& other) noexcept {
        // 逐元素交换(或用std::swap_ranges,效率更高)
        for (size_type i = 0; i < N; ++i) {
            std::swap(_M_elems[i], other._M_elems[i]);
        }
    }

    // ========== 空数组特化(N=0) ==========
    // 当N=0时,_M_elems为空,需特殊处理迭代器(避免指针越界)
    template <typename T>
    class array<T, 0> {
        // 空数组无底层存储,迭代器返回nullptr或特殊标记
        // 核心接口:size()=0,empty()=true,at()抛异常等
    };
};

// ========== 全局swap函数(重载,匹配容器规范) ==========
template <typename T, size_t N>
void swap(array<T, N>& a, array<T, N>& b) noexcept {
    a.swap(b);
}

} // namespace std
相关推荐
我材不敲代码3 小时前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
身如柳絮随风扬4 小时前
Java中的CAS机制详解
java·开发语言
-dzk-5 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
韩立学长5 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
froginwe115 小时前
Scala 循环
开发语言
m0_706653236 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你916 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Bruk.Liu6 小时前
(LangChain实战2):LangChain消息(message)的使用
开发语言·langchain
qq_423233906 小时前
C++与Python混合编程实战
开发语言·c++·算法
m0_715575346 小时前
分布式任务调度系统
开发语言·c++·算法