【C++ STL】std::array

第一章 std::array 容器函数列表与讲解

1.1 构造与初始化函数

默认构造函数

  • 函数功能: 构造一个默认初始化的 std::array 对象,内置类型元素为不确定值,类类型元素调用默认构造函数
  • 函数入参: 无参数
  • 函数返回值: 无(构造函数)
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr;
arr.fill(0);

聚合初始化

  • 函数功能: 通过初始化列表进行聚合初始化,可完全或部分初始化数组元素,未显式初始化的元素执行值初始化
  • 函数入参: 元素数量不超过数组大小的初始化列表
  • 函数返回值: 无
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
std::array<int, 5> arr2 = { 10, 20 };

拷贝构造函数

  • 函数功能: 用同类型、同大小的另一个 std::array 拷贝构造新对象,每个元素逐一拷贝
  • 函数入参: const std::array<T, N>& other 源数组对象
  • 函数返回值: 无(构造函数)
  • 使用举例:
cpp 复制代码
std::array<int, 4> original = { 1, 2, 3, 4 };
std::array<int, 4> copied = original;

移动构造函数

  • 函数功能: 用同类型、同大小的另一个 std::array 移动构造新对象,元素执行移动语义,优化非基础类型性能
  • 函数入参: std::array<T, N>&& other 源数组右值引用
  • 函数返回值: 无(构造函数)
  • 使用举例:
cpp 复制代码
std::array<std::string, 3> original = { "aaa", "bbb", "ccc" };
std::array<std::string, 3> moved = std::move(original);

值初始化

  • 函数功能: 通过空花括号进行值初始化,所有元素执行零初始化(内置类型置0,类类型调用默认构造)
  • 函数入参: 空花括号初始化器
  • 函数返回值: 无
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr{};

类模板参数推导(C++17 推导指引)

  • 函数功能: C++17 起支持通过初始化列表自动推导 std::array 的元素类型和数组大小,无需显式指定模板参数
  • 函数入参: 初始化列表
  • 函数返回值: 推导后的 std::array 对象
  • 使用举例:
cpp 复制代码
std::array arr = { 1, 2, 3, 4, 5 };

constexpr 构造

  • 函数功能: 在编译期构造 std::array 常量对象,可用于常量表达式场景,配合 static_assert 做编译期校验
  • 函数入参: 常量初始化列表
  • 函数返回值: constexpr 修饰的 std::array 常量对象
  • 使用举例:
cpp 复制代码
constexpr std::array<int, 4> arr = { 10, 20, 30, 40 };
static_assert(arr.size() == 4, "size must be 4");

std::to_array(C++20)

  • 函数功能: C++20 标准库非成员函数,将C风格数组或初始化列表转换为 std::array 对象,支持移动语义和显式指定元素类型
  • 函数入参:
    • C风格数组(支持左值、右值)
    • 或 std::initializer_list 初始化列表
    • 可显式指定元素类型模板参数
  • 函数返回值: 对应类型和大小的 std::array 对象
  • 使用举例:
cpp 复制代码
int c_arr[] = { 1, 2, 3, 4, 5 };
auto arr1 = std::to_array(c_arr);
auto arr2 = std::to_array<std::string>({"hello", "world"});

1.2 元素访问函数

operator[]

  • 函数功能: 下标访问指定位置的元素,不进行越界检查,越界行为未定义
  • 函数入参: size_type pos 元素索引,从0开始
  • 函数返回值: 对应位置元素的引用(可读写)
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
int val = arr[0];
arr[0] = 99;

at

  • 函数功能: 访问指定位置的元素,带边界检查,越界时抛出 std::out_of_range 异常
  • 函数入参: size_type pos 元素索引
  • 函数返回值: 对应位置元素的引用
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
int val = arr.at(1);
arr.at(10); // 越界抛出异常

front

  • 函数功能: 访问数组第一个元素,空数组调用行为未定义
  • 函数入参: 无
  • 函数返回值: 首元素的引用
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
int first = arr.front();
arr.front() = 100;

back

  • 函数功能: 访问数组最后一个元素,空数组调用行为未定义
  • 函数入参: 无
  • 函数返回值: 尾元素的引用
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
int last = arr.back();
arr.back() = 200;

data

  • 函数功能: 返回指向数组首元素的底层裸指针,可直接操作连续内存,兼容C风格接口
  • 函数入参: 无
  • 函数返回值: T* 指向首元素的指针;const对象返回 const T*
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
int* ptr = arr.data();
std::memset(arr.data(), 0, arr.size() * sizeof(int));

std::get

  • 函数功能: 非成员函数,通过编译期常量索引访问数组元素,索引越界会触发编译错误
  • 函数入参: 模板参数 size_t I 编译期索引;函数参数为 std::array 对象引用
  • 函数返回值: 对应位置元素的引用
  • 使用举例:
cpp 复制代码
std::array<int, 4> arr = { 100, 200, 300, 400 };
int val = std::get<0>(arr);
std::get<1>(arr) = 999;

1.3 迭代器相关函数

begin / end

  • 函数功能: 返回指向首元素的正向迭代器(begin)和尾后迭代器(end),用于正向遍历数组
  • 函数入参: 无
  • 函数返回值: iterator 类型迭代器,可修改元素
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = {1, 2, 3, 4, 5 };
for (auto it = arr.begin(); it != arr.end(); it++) {
    std::cout << *it << " ";
}

cbegin / cend

  • 函数功能: 返回指向首元素的常量正向迭代器(cbegin)和常量尾后迭代器(cend),仅可读不可修改元素
  • 函数入参: 无
  • 函数返回值: const_iterator 类型常量迭代器
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
for (auto it = arr.cbegin(); it != arr.cend(); it++) {
    std::cout << *it << " ";
}

rbegin / rend

  • 函数功能: 返回指向尾元素的反向迭代器(rbegin)首前反向迭代器(rend),用于反向遍历数组
  • 函数入参: 无
  • 函数返回值: reverse_iterator 类型反向迭代器
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
for (auto it = arr.rbegin(); it != arr.rend(); it++) {
    std::cout << *it << " ";
}

crbegin / crend

  • 函数功能: 返回指向尾元素的常量反向迭代器(crbegin)和首前常量反向迭代器(crend),反向只读遍历
  • 函数入参: 无
  • 函数返回值: const_reverse_iterator 类型常量反向迭代器
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
for (auto it = arr.crbegin(); it != arr.crend(); it++) {
    std::cout << *it << " ";
}

1.4 容量查询函数

size

  • 函数功能: 返回数组中元素的数量,即模板参数 N 的值,为编译期常量
  • 函数入参: 无
  • 函数返回值: size_type 数组元素个数
  • 使用举例:
cpp 复制代码
std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << arr.size();

max_size

  • 函数功能: 返回数组最多可容纳的元素数量,std::array 固定大小,因此与 size() 返回值相同
  • 函数入参: 无
  • 函数返回值: size_type 最大元素个数
  • 使用举例:
cpp 复制代码
std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << arr.max_size();

empty

  • 函数功能: 判断数组是否为空(元素数量为0)
  • 函数入参: 无
  • 函数返回值: bool,空返回 true,否则返回 false
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
std::array<int, 0> arr2 = {};
std::cout << arr1.empty();
std::cout << arr2.empty();

1.5 修改操作函数

fill

  • 函数功能: 将数组中所有元素替换为指定值
  • 函数入参: const T& value 要填充的值
  • 函数返回值: 无
  • 使用举例:
cpp 复制代码
std::array<int, 5> arr;
arr.fill(42);

swap 成员函数

  • 函数功能: 与另一个同类型、同大小的数组交换所有元素内容
  • 函数入参: std::array<T, N>& other 待交换的数组
  • 函数返回值: 无
  • 使用举例:
cpp 复制代码
std::array<int, 3> arr1 = { 1, 2, 3 };
std::array<int, 3> arr2 = { 10, 20, 30 };
arr1.swap(arr2);

std::swap 非成员函数

  • 函数功能: 标准库非成员重载,交换两个 std::array 的内容,效果同成员 swap
  • 函数入参: 两个同类型、同大小的 std::array 对象引用
  • 函数返回值: 无
  • 使用举例:
cpp 复制代码
std::array<int, 3> arr1 = { 1, 2, 3 };
std::array<int, 3> arr2 = { 10, 20, 30 };
std::swap(arr1, arr2);

拷贝赋值运算符

  • 函数功能: 将另一个数组的所有元素拷贝赋值给当前数组
  • 函数入参: const std::array<T, N>& other 源数组
  • 函数返回值: std::array<T, N>& 当前对象的引用
  • 使用举例:
cpp 复制代码
std::array<int, 4> arr1 = { 1, 2, 3, 4 };
std::array<int, 4> arr2;
arr2 = arr1;

移动赋值运算符

  • 函数功能: 将另一个数组的所有元素移动赋值给当前数组,适合非基础类型优化性能
  • 函数入参: std::array<T, N>&& other 源数组右值引用
  • 函数返回值: std::array<T, N>& 当前对象的引用
  • 使用举例:
cpp 复制代码
std::array<std::string, 3> arr1 = { "hello", "world", "cpp" };
std::array<std::string, 3> arr2;
arr2 = std::move(arr1);

1.6 比较操作函数

关系比较运算符(==、!=、<、>、<=、>=)

  • 函数功能: 按字典序逐元素比较两个同类型、同大小数组的大小关系
  • 函数入参: 两个 const std::array<T, N>& 待比较的数组
  • 函数返回值: bool,比较结果
  • 使用举例:
cpp 复制代码
std::array<int, 3> a = { 1, 2, 3 };
std::array<int, 3> b = { 1, 2, 4 };
bool eq = (a == b);
bool lt = (a < b);

三路比较运算符 <=>(C++20)

  • 函数功能: C++20 引入,逐元素三路比较数组,返回比较类别对象,可一次性推导所有大小关系
  • 函数入参: 两个 const std::array<T, N>& 待比较的数组
  • 函数返回值: 对应比较类别(如 std::strong_ordering
  • 使用举例:
cpp 复制代码
std::array<int, 3> a = { 1, 2, 3 };
std::array<int, 3> b = { 1, 2, 4 };
auto result = (a <=> b);

1.7 元组接口相关

std::tuple_size_v

  • 函数功能: 编译期获取 std::array 的元素数量,属于元组式接口,值等于数组大小 N
  • 函数入参: 模板参数为 std::array 类型
  • 函数返回值: 编译期常量 size_t
  • 使用举例:
cpp 复制代码
constexpr auto sz = std::tuple_size_v<std::array<int, 3>>;

std::tuple_element_t

  • 函数功能: 编译期获取 std::array 指定索引位置的元素类型,属于元组式接口
  • 函数入参: 模板参数 size_t I(索引)和 std::array 类型
  • 函数返回值: 对应位置的元素类型
  • 使用举例:
cpp 复制代码
using ElemType = std::tuple_element_t<0, std::array<int, 3>>;

第二章 分模块代码解析

2.1 非基础类型定义

模块说明 :本部分定义了PointStudent两个自定义类,均完整重载了相等比较、大小比较与流输出运算符,用于后续演示std::array对自定义类型的存储、排序、批量操作等能力,验证标准容器与自定义类型的兼容性。

cpp 复制代码
class Point
{
private:
    double x_;
    double y_;
public:
    Point() : x_(0), y_(0) { }
    Point(double x, double y) : x_(x), y_(y) { }
    bool operator==(const Point& other) const
    {
        return x_ == other.x_ && y_ == other.y_;
    }
    bool operator!=(const Point& other) const
    {
        return !(*this == other);
    }
    bool operator<(const Point& other) const
    {
        if (x_ != other.x_) return x_ < other.x_;
        return y_ < other.y_;
    }
    bool operator<=(const Point& other) const
    {
        return !(other < *this);
    }
    bool operator>(const Point& other) const
    {
        return other < *this;
    }
    bool operator>=(const Point& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const Point& p)
    {
        os << "(" << p.x_ << ", " << p.y_ << ")";
        return os;
    }

    double getX() const { return x_; }
    double getY() const { return y_; }

    void setX(double x) { x_ = x; }
    void setY(double y) { y_ = y; }
};

class Student
{
private:
    int id_;
    std::string name_;
    double score_;
public:
    Student() : id_(0), name_(""), score_(0.0) { }
    Student(int id, const std::string& name, double score)
        : id_(id), name_(name), score_(score) { }
    bool operator==(const Student& other) const
    {
        return id_ == other.id_ && name_ == other.name_ && score_ == other.score_;
    }
    bool operator<(const Student& other) const
    {
        return score_ > other.score_;
    }

    friend std::ostream& operator<<(std::ostream& os, const Student& s)
    {
        os << "Student[" << s.id_ << ", " << s.name_ << ", " << s.score_ << "]";
        return os;
    }

    int getId() const { return id_; }
    std::string getName() const { return name_; }
    double getScore() const { return score_; }

    void setId(int id) { id_ = id; }
    void setName(const std::string& name) { name_ = name; }
    void setScore(double score) { score_ = score; }
};

2.2 声明与初始化

模块说明 :完整覆盖std::array从C++11到C++20的所有主流初始化方式,包含默认构造、聚合初始化、拷贝/移动构造、值初始化、自定义类型初始化、编译期初始化等场景,是std::array最核心的基础用法。

2.2.1 默认初始化

说明 :演示默认构造方式创建std::array。默认构造下内置类型元素为未初始化的不确定值,因此示例中配合fill()方法统一赋值,避免读取脏数据。

cpp 复制代码
void demoDefaultInit()
{
    std::array<int, 5> arr;
    arr.fill(0);
    std::cout << "[默认初始化] ";
    for (const auto& elem : arr)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

2.2.2 聚合初始化

说明 :演示聚合初始化语法,这是std::array最常用的初始化方式。支持完全初始化(元素数量匹配数组大小)与部分初始化(未显式赋值的元素自动执行值初始化,内置类型置零)。

cpp 复制代码
void demoAggregateInit()
{
    std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
    std::array<int, 5> arr2 = { 10, 20 };
    std::array<std::string, 3> arr3 = { "hello", "world", "cpp" };
    
    std::cout << "[聚合初始化-完全] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[聚合初始化-部分] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[聚合初始化-字符串] ";
    for (const auto& e : arr3) std::cout << e << " ";
    std::cout << std::endl;
}

2.2.3 拷贝初始化

说明:演示拷贝构造函数,用已有数组完整复制出一个新数组,所有元素逐一拷贝,新旧数组互不影响。

cpp 复制代码
void demoCopyInit()
{
    std::array<int, 4> original = { 1, 2, 3, 4 };
    std::array<int, 4> copied = original;
    std::cout << "[拷贝初始化] ";
    for (const auto& e : copied) std::cout << e << " ";
    std::cout << std::endl;
}

2.2.4 移动初始化

说明 :演示移动构造函数,通过std::move将原数组的元素所有权转移给新数组。对于std::string等非基础类型,移动语义可避免深拷贝,提升性能;原数组元素进入有效但未指定的状态。

cpp 复制代码
void demoMoveInit()
{
    std::array<std::string, 3> original = { "aaa", "bbb", "ccc" };
    std::array<std::string, 3> moved = std::move(original);
    std::cout << "[移动初始化] ";
    for (const auto& e : moved) std::cout << e << " ";
    std::cout << std::endl;
}

2.2.5 值初始化

说明:演示空花括号值初始化,数组内所有元素执行零初始化(内置类型置0,类类型调用默认构造),是最安全的清零初始化方式。

cpp 复制代码
void demoValueInit()
{
    std::array<int, 5> arr{};
    std::cout << "[值初始化] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.2.6 自定义类型初始化

说明 :演示std::array存储自定义类类型的初始化方式,直接通过类构造函数创建对象并完成数组初始化。

cpp 复制代码
void demoClassTypeInit()
{
    std::array<Point, 3> points = {
        Point(1.0, 2.0),
        Point(3.0, 4.0),
        Point(5.0, 6.0)
    };
    std::cout << "[自定义类型初始化] ";
    for (const auto& p : points) std::cout << p << " ";
    std::cout << std::endl;
}

2.2.7 模板推导指引 C++17

说明 :演示C++17引入的类模板参数推导(CTAD)特性,无需显式指定元素类型与数组大小,编译器可根据初始化列表自动推导std::array的模板参数,简化写法。

cpp 复制代码
void demoDeductionGuide()
{
#if _MSVC_LANG >= 201703L
    // C++14 及以前 ------ 必须写全 std::array<int, 5> arr = {1, 2, 3, 4, 5};
    // C++17 ------ 编译器推导出: std::array<int, 5>
    std::array arr = { 1, 2, 3, 4, 5 };
    std::cout << "[推导指引(C++17)] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
#else
    std::cout << "[推导指引(C++17)] 需要C++17支持" << std::endl;
#endif
}

2.2.8 constexpr初始化

说明 :演示constexpr修饰的编译期常量数组,数组在编译阶段完成构造与赋值,可配合static_assert做编译期校验,提升运行时性能。

cpp 复制代码
void demoConstexprInit()
{
    constexpr std::array<int, 4> arr = { 10, 20, 30, 40 };
    static_assert(arr.size() == 4, "size must be 4");
    static_assert(arr[0] == 10, "first element must be 10");
    std::cout << "[constexpr初始化]";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.2.9 std::to_array (C++20)

说明 :演示C++20新增的std::to_array工具函数,可将C风格原生数组、初始化列表快速转换为std::array对象,支持显式指定元素类型与移动语义,是C数组与std::array互转的标准方式。

cpp 复制代码
void demoToArray()
{
#if _MSVC_LANG >= 202002L
    int c_arr[] = { 1, 2, 3, 4, 5 };
    auto arr1 = std::to_array(c_arr);
    auto arr2 = std::to_array({ 10, 20, 30 });
    auto arr3 = std::to_array<std::string>({"hello", "world"});
    std::cout << "[std::to_array(C++20)-从C数组] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[std::to_array(C++20)-从初始化列表] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[std::to_array(C++20)-指定类型] ";
    for (const auto& e : arr3) std::cout << e << " ";
    std::cout << std::endl;
#else
    std::cout << "[std::to_array(C++20)] 需要C++20支持" << std::endl;
#endif
}

void demoToArrayMove()
{
#if _MSVC_LANG >= 202002L
    std::string strs[] = { "hello", "world", "cpp" };
    auto arr = std::to_array(std::move(strs));
    std::cout << "[std::to_array(C++20)-移动语义] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
#endif
}

2.3 元素访问

模块说明 :演示std::array的6种元素访问方式,涵盖下标访问、安全访问、首尾元素、底层指针、编译期索引等场景,不同方式在安全性、性能、使用场景上有明确区别。

2.3.1 operator\[\]

说明:演示下标运算符访问元素,性能最高、最常用,但不做越界检查,越界访问属于未定义行为,需开发者自行保证索引合法性。支持读操作与写操作。

cpp 复制代码
void demoOperatorBracket()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[operator[]] arr[0]=" << arr[0] << ", arr[2]=" << arr[2] << std::endl;
    arr[0] = 99;
    std::cout << "[operator[]修改后] arr[0]=" << arr[0] << std::endl;
}

2.3.2 at()

说明 :演示at()成员函数访问元素,带运行时边界检查,索引越界时会抛出std::out_of_range异常,安全性更高,但性能略低于operator[]

cpp 复制代码
void demoAt()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[at()] arr.at(1)=" << arr.at(1) << std::endl;
    try
    {
        arr.at(10);
    }
    catch (const std::out_of_range& e)
    {
        std::cout << "[at()越界异常] " << e.what() << std::endl;
    }
}

2.3.3 front()

说明 :演示front()获取数组首元素的引用,空数组调用为未定义行为。可直接通过返回值修改首元素。

cpp 复制代码
void demoFront()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[front()] " << arr.front() << std::endl;
    arr.front() = 100;
    std::cout << "[front()修改后] " << arr.front() << std::endl;
}

2.3.4 back()

说明 :演示back()获取数组尾元素的引用,空数组调用为未定义行为。可直接通过返回值修改尾元素。

cpp 复制代码
void demoBack()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[back()} " << arr.back() << std::endl;
    arr.back() = 200;
    std::cout << "[back()修改后] " << arr.back() << std::endl;
}

2.3.5 data()

说明 :演示data()获取数组底层连续内存的首指针,可兼容C风格接口、直接操作内存(如memset),是std::array与原生C代码交互的核心接口。

cpp 复制代码
void demoData()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    int* ptr = arr.data();
    std::cout << "[data()] 通过指针访问: ";
    for (size_t i = 0; i < arr.size(); i++)
    {
        std::cout << ptr[i] << " ";
    }
    std::cout << std::endl;
    std::memset(arr.data(), 0, arr.size() * sizeof(int));
    std::cout << "[data()配合memset] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.3.6 std::get

说明 :演示非成员函数std::get<>通过编译期常量索引访问元素,索引越界会直接触发编译错误,属于编译期安全的访问方式,同时支持元编程场景。

cpp 复制代码
void demoStdGet()
{
    std::array<int, 4> arr = { 100, 200, 300, 400 };
    std::cout << "[std::get<0>] " << std::get<0>(arr) << std::endl;
    std::cout << "[std::get<2>] " << std::get<2>(arr) << std::endl;
    std::get<1>(arr) = 999;
    std::cout << "[std::get修改后] arr[1]=" << arr[1] << std::endl;
}

2.4 迭代器操作

模块说明 :演示std::array的四类迭代器与迭代器算术运算。std::array的迭代器属于随机访问迭代器,支持完整的算术运算、比较运算,可无缝对接所有STL算法。

2.4.1 begin / end

说明 :演示正向迭代器begin()(指向首元素)与end()(指向尾元素的下一个位置),用于正向遍历数组,可通过迭代器修改元素。

cpp 复制代码
void demoBeginEnd()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5 };
    std::cout << "[begin/end正向遍历] ";
    for (auto it = arr.begin(); it != arr.end(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

2.4.2 cbegin / cend

说明 :演示常量正向迭代器cbegin()cend(),遍历过程中无法修改元素,适用于只读遍历场景,保证数据安全性。

cpp 复制代码
void demoCBeginCEnd()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[cbegin/cend常量遍历] ";
    for (auto it = arr.cbegin(); it != arr.cend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

2.4.3 rbegin / rend

说明 :演示反向迭代器rbegin()(指向尾元素)与rend()(指向首元素的前一个位置),用于从后往前反向遍历数组。

cpp 复制代码
void demoRbeginRend()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[rbegin/rend反向遍历] ";
    for (auto it = arr.rbegin(); it != arr.rend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

2.4.4 crbegin / crend

说明 :演示常量反向迭代器crbegin()crend(),只读方式反向遍历数组。

cpp 复制代码
void demoCRbeginCRend()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[crbegin/crend常量反向遍历] ";
    for (auto it = arr.crbegin(); it != arr.crend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

2.4.5 iterator arithmetic

说明:演示随机访问迭代器的算术特性:支持迭代器与整数加减、两个迭代器相减求距离、迭代器大小比较,是数组迭代器的独有优势。

cpp 复制代码
void demoIteratorArithmetic()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    auto it = arr.begin();
    std::cout << "[迭代器算数] it+2 -> " << *(it + 2) << std::endl;
    std::cout << "[迭代器距离] end - begin = " << (arr.end() - arr.begin()) << std::endl;
    auto it2 = arr.begin() + 3;
    std::cout << "[迭代器比较] it < it2 : " << (it < it2 ? "true" : "false") << std::endl;
}

2.5 容量查询

模块说明 :演示std::array的容量查询接口。std::array是固定大小容器,大小在编译期确定,所有容量接口均为编译期常量,无运行时开销。

2.5.1 size

说明 :演示size()获取数组元素个数,返回值等于模板参数中的大小N,为编译期常量。

cpp 复制代码
void demoSize()
{
    std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
    std::cout << "[size()] " << arr.size() << std::endl;
}

2.5.2 max_size

说明 :演示max_size()获取数组最多可容纳的元素数。由于std::array大小固定,该返回值与size()完全一致,该接口主要为了兼容其他STL容器的通用接口规范。

cpp 复制代码
void demoMaxSize()
{
    std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
    std::cout << "[max_size()] " << arr.max_size() << std::endl;
}

2.5.3 empty

说明 :演示empty()判断数组是否为空(元素数为0),主要用于零长度数组场景,通用模板代码中可通过该接口做边界判断。

cpp 复制代码
void demoEmpty()
{
    std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
    std::array<int, 0> arr2 = {};
    std::cout << "[empty()] arr1: " << (arr1.empty() ? "true" : "false") << std::endl;
    std::cout << "[empty()] arr2(size=0): " << (arr2.empty() ? "true" : "false") << std::endl;
}

2.6 修改操作

模块说明 :演示std::array支持的修改操作。由于大小固定,std::array不支持插入、删除元素,仅支持整体填充、交换、整体赋值三类修改操作。

2.6.1 fill

说明 :演示fill()方法,将数组内所有元素统一设置为指定值,是批量重置数组的高效方式。

cpp 复制代码
void demoFill()
{
    std::array<int, 5> arr;
    arr.fill(42);
    std::cout << "[fill(42)] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.6.2 swap

说明 :演示swap成员函数,交换两个同类型、同大小数组的全部元素内容,时间复杂度为O(N)。

cpp 复制代码
void demoSwap()
{
    std::array<int, 3> arr1 = { 1, 2, 3 };
    std::array<int, 3> arr2 = { 10, 20, 30 };
    arr1.swap(arr2);
    std::cout << "[swap后 arr1] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[swap后 arr2] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}

2.6.3 std::swap

说明 :演示标准库非成员std::swap重载,功能与成员swap完全一致,符合STL容器的通用交换规范,推荐泛型编程中使用。

cpp 复制代码
void demoStdSwap()
{
    std::array<int, 3> arr1 = { 1, 2, 3 };
    std::array<int, 3> arr2 = { 10, 20, 30 };
    std::swap(arr1, arr2);
    std::cout << "[std::swap后 arr1] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
}

2.6.4 拷贝赋值

说明:演示拷贝赋值运算符,将一个数组的所有元素完整拷贝到另一个同类型数组,覆盖目标数组原有内容。

cpp 复制代码
void demoAssignment()
{
    std::array<int, 4> arr1 = { 1, 2, 3, 4 };
    std::array<int, 4> arr2;
    arr2 = arr1;
    std::cout << "[拷贝赋值] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}

2.6.5 移动赋值

说明:演示移动赋值运算符,将源数组的元素所有权转移到目标数组,对于复杂类型可避免拷贝开销,提升性能。

cpp 复制代码
void demoMoveAssignment()
{
    std::array<std::string, 3> arr1 = { "hello", "world", "cpp" };
    std::array<std::string, 3> arr2;
    arr2 = std::move(arr1);
    std::cout << "[移动赋值] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}

2.7 比较操作

模块说明 :演示std::array的比较运算,采用字典序逐元素比较规则,两个数组只有大小相同、类型相同才能比较。

2.7.1 比较操作符

说明:演示六种传统关系运算符(==、!=、<、>、<=、>=),按从前到后的顺序逐元素比较,第一对不相等的元素决定整体大小关系;所有元素都相等则两数组相等。

cpp 复制代码
void demoComparisonOperators()
{
    std::array<int, 3> a = { 1, 2, 3 };
    std::array<int, 3> b = { 1, 2, 3 };
    std::array<int, 3> c = { 1, 2, 4 };
    std::array<int, 3> d = { 1, 2, 2 };
    std::cout << "[==] a == b : " << (a == b ? "true" : "false") << std::endl;
    std::cout << "[!=] a != b : " << (a != b ? "true" : "false") << std::endl;
    std::cout << "[<] a < c : " << (a < c ? "true" : "false") << std::endl;
    std::cout << "[>] a > d : " << (a > d ? "true" : "false") << std::endl;
    std::cout << "[<=] a <= b : " << (a <= b ? "true" : "false") << std::endl;
    std::cout << "[>=] a >= c : " << (a >= c ? "true" : "false") << std::endl;
}

2.7.2 三路比较

说明 :演示C++20新增的三路比较运算符<=>,一次运算即可得出完整的大小关系,返回比较类别对象,可同时推导所有关系运算结果。

cpp 复制代码
void demoThreeWayComparison()
{
#if _MSVC_LANG >= 202002L
    std::array<int, 3> a = { 1, 2, 3 };
    std::array<int, 3> b = { 1, 2, 4 };
    auto result = (a <=> b);
    if (result < 0)
    {
        std::cout << "[<=>] a < b" << std::endl;
    }
    else if (result > 0)
    {
        std::cout << "[<=>] a > b" << std::endl;
    }
    else
    {
        std::cout << "[<=>] a == b" << std::endl;
    }
#else
    std::cout << "[<=>] 需要C++20支持" << std::endl;
#endif
}

2.8 与STL算法配合

模块说明 :演示std::array与STL标准算法的协同使用。std::array提供标准迭代器接口,可无缝对接所有STL算法,是固定大小数组的核心优势之一。

2.8.1 sort

说明 :演示std::sort排序算法,默认升序排列,也可传入std::greater等比较函数实现降序。

cpp 复制代码
void demoAlgoSort()
{
    std::array<int, 6> arr = { 5, 3, 1, 4, 6, 2 };
    std::sort(arr.begin(), arr.end());
    std::cout << "[sort升序] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    std::sort(arr.begin(), arr.end(), std::greater<int>());
    std::cout << "[sort降序] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.2 find

说明 :演示std::find线性查找算法,查找指定值的元素,返回对应迭代器;未找到则返回end()

cpp 复制代码
void demoAlgoFind()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    auto it = std::find(arr.begin(), arr.end(), 30);
    if (it != arr.end())
    {
        std::cout << "[find] 找到30, 索引=" << std::distance(arr.begin(), it) << std::endl;
    }
    auto it2 = std::find(arr.begin(), arr.end(), 99);
    if (it2 == arr.end())
    {
        std::cout << "[find] 未找到99" << std::endl;
    }
}

2.8.3 accumulate

说明 :演示std::accumulate累加算法,计算数组所有元素的和,第三个参数为累加初始值。

cpp 复制代码
void demoAlgoAccumulate()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int sum = std::accumulate(arr.begin(), arr.end(), 0);
    std::cout << "[accumulate] sum=" << sum << std::endl;
}

2.8.4 minmax

说明 :演示std::minmax_element算法,一次遍历同时获取数组最小值与最大值的迭代器,配合C++17结构化绑定可便捷接收结果。

cpp 复制代码
void demoAlgoMinMax()
{
#if _MSVC_LANG >= 201703L
    std::array<int, 5> arr = { 3, 1, 4, 1, 5 };
    auto [minIt, maxIt] = std::minmax_element(arr.begin(), arr.end());
    std::cout << "[minmax_element] min=" << *minIt << ", max=" << *maxIt << std::endl;
#endif
}

2.8.5 count

说明 :演示std::count计数算法,统计数组中指定值出现的次数。

cpp 复制代码
void demoAlgoCount()
{
    std::array<int, 8> arr = { 1, 2, 2, 3, 2, 4, 2, 5 };
    auto cnt = std::count(arr.begin(), arr.end(), 2);
    std::cout << "[count] 2出现了 " << cnt << " 次" << std::endl;
}

2.8.6 transform

说明 :演示std::transform变换算法,对数组每个元素执行指定操作(如平方计算),将结果写入目标数组。

cpp 复制代码
void demoAlgoTransform()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::array<int, 5> result;
    std::transform(arr.begin(), arr.end(), result.begin(),
        [](int x) { return x * x; }
    );
    std::cout << "[transform平方] ";
    for (const auto& e : result) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.7 for_each

说明 :演示std::for_each遍历算法,对每个元素执行指定的回调操作,适合批量处理元素。

cpp 复制代码
void demoAlgoForEach()
{
    std::array<std::string, 3> arr = { "hello", "world", "cpp" };
    std::cout << "[for_each]";
    std::for_each(arr.begin(), arr.end(), [](const std::string& s) { std::cout << s << " "; });
    std::cout << std::endl;
}

2.8.8 reverse

说明 :演示std::reverse反转算法,将数组内元素的顺序原地反转。

cpp 复制代码
void demoAlgoReverse()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::reverse(arr.begin(), arr.end());
    std::cout << "[reverse] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.9 copy

说明 :演示std::copy拷贝算法,将源数组元素完整复制到目标数组。

cpp 复制代码
void demoAlgoCopy()
{
    std::array<int, 5> src = { 1, 2, 3, 4, 5 };
    std::array<int, 5> dst{};
    std::copy(src.begin(), src.end(), dst.begin());
    std::cout << "[copy] ";
    for (const auto& e : dst) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.10 replace

说明 :演示std::replace替换算法,将数组中所有等于指定值的元素替换为新值。

cpp 复制代码
void demoAlgoReplace()
{
    std::array<int, 6> arr = { 1, 2, 3, 2, 4, 2 };
    std::replace(arr.begin(), arr.end(), 2, 99);
    std::cout << "[replace] 2->99: ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.11 all_of / any_of / none_of

说明 :演示三个谓词判断算法:all_of判断是否所有元素都满足条件,any_of判断是否存在元素满足条件,none_of判断是否所有元素都不满足条件。

cpp 复制代码
void demoAlgoAnyAllNone()
{
    std::array<int, 5> arr = { 2, 4, 6, 8, 10 };
    bool allEven = std::all_of(arr.begin(), arr.end(), [](int x) { return x % 2 == 0; });
    bool anyGt5 = std::any_of(arr.begin(), arr.end(), [](int x) { return x > 5; });
    bool nonNeg = std::none_of(arr.begin(), arr.end(), [](int x) { return x < 0; });
    std::cout << "[all_of全偶数] " << (allEven ? "true" : "false") << std::endl;
    std::cout << "[any_of有>5] " << (anyGt5 ? "true" : "false") << std::endl;
    std::cout << "[none_of无负数] " << (nonNeg ? "true" : "false") << std::endl;
}

说明 :演示有序数组的二分查找相关算法:std::binary_search判断值是否存在;std::lower_bound找第一个不小于目标值的位置;std::upper_bound找第一个大于目标值的位置。

cpp 复制代码
void demoAlgoBinarySearch()
{
    std::array<int, 6> arr = { 1, 3, 5, 7, 9, 11 };
    bool found = std::binary_search(arr.begin(), arr.end(), 7);
    std::cout << "[binary_search] 找7 " << (found ? "true" : "false") << std::endl;
    auto lb = std::lower_bound(arr.begin(), arr.end(), 5);
    auto ub = std::upper_bound(arr.begin(), arr.end(), 5);
    std::cout << "[lower_bound(5)] 索引=" << std::distance(arr.begin(), lb) << std::endl;
    std::cout << "[upper_bound(5)] 索引=" << std::distance(arr.begin(), ub) << std::endl;
}

2.8.13 unique

说明 :演示std::unique去重算法,去除相邻的重复元素,返回去重后的尾迭代器。注意std::array大小固定,去重后尾部仍保留原有元素,有效范围为begin()到返回的新尾迭代器。

cpp 复制代码
void demoAlgoUnique()
{
    std::array<int, 7> arr = { 1, 1, 2, 2, 3, 3, 3 };
    auto newEnd = std::unique(arr.begin(), arr.end());
    std::cout << "[unique]后 ";
    for (auto it = arr.begin(); it != arr.end(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "(去重后有效元素数=" << std::distance(arr.begin(), newEnd) << ")" << std::endl;
}

2.8.14 rotate

说明 :演示std::rotate旋转算法,以指定位置为轴左旋数组,将该位置之前的元素整体移动到数组尾部。

cpp 复制代码
void demoAlgoRotate()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::rotate(arr.begin(), arr.begin() + 2, arr.end());
    std::cout << "[rotate]左旋2位 ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.15 iota

说明 :演示std::iota递增填充算法,从指定起始值开始,依次递增填充数组所有元素。

cpp 复制代码
void demoAlgoIota()
{
    std::array<int, 5> arr;
    std::iota(arr.begin(), arr.end(), 1);
    std::cout << "[iota]从1开始 ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.8.16 partial_sum

说明 :演示std::partial_sum前缀和算法,计算数组的前缀和序列并写入目标数组。

cpp 复制代码
void demoAlgoPartialSum()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::array<int, 5> result;
    std::partial_sum(arr.begin(), arr.end(), result.begin());
    std::cout << "[partial_sum]前缀和 ";
    for (const auto& e : result) std::cout << e << " ";
    std::cout << std::endl;
}

2.9 结构化绑定 C++17

模块说明 :演示C++17结构化绑定在std::array上的应用。std::array支持元组式接口,可通过结构化绑定一次性解包多个元素,支持值绑定、引用绑定、const引用绑定。

2.9.1 引用修改

说明:演示值拷贝绑定与引用绑定两种方式:值绑定生成独立副本;引用绑定直接绑定数组元素,可通过绑定变量修改原数组内容。

cpp 复制代码
void demoStructedBindings()
{
#if _MSVC_LANG >= 201703L
    std::array<int, 3> arr = { 100, 200, 300 };
    auto [a, b, c] = arr;
    std::cout << "[结构化绑定] a=" << a << ", b=" << b << ", c=" << c << std::endl;
    auto& [x, y, z] = arr;
    x = 999;
    std::cout << "[结构化绑定-引用修改] arr[0]=" << arr[0] << std::endl;
#else
    std::cout << "[结构化绑定] 需要支持C++17" << std::endl;
#endif
}

2.9.2 const引用

说明:演示const引用方式的结构化绑定,只读访问数组元素,避免拷贝同时保证数据不被修改。

cpp 复制代码
void demoStructedBindingsConst()
{
#if _MSVC_LANG >= 201703L
    const std::array<std::string, 3> arr = { "alpha", "beta", "gamma" };
    const auto& [first, second, third] = arr;
    std::cout << "[结构化绑定-const引用] " << first << ", " << second << ", " << third << std::endl;
#else
    std::cout << "[结构化绑定] 需要支持C++17" << std::endl;
#endif
}

2.10 函数传参与返回

模块说明 :演示std::array作为函数参数与返回值的四种常用方式,不同传递方式在拷贝开销、修改权限上有明显区别。包含值传递(内部修改不影响外部)、const引用传递(只读无拷贝)、引用传递(可修改原数组)三种传参方式,以及函数直接返回std::array的用法(编译器返回值优化可避免额外拷贝)。

cpp 复制代码
// 值传递-内部修改
void processByValue(std::array<int, 5> arr)
{
    arr[0] = 999;
    std::cout << "[值传递-内部修改] arr[0]=" << arr[0] << std::endl;
}
// const引用传递
void processByConstRef(const std::array<int, 5>& arr)
{
    std::cout << "[const引用传递] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}
// 引用传递
void processByRef(std::array<int, 5>& arr)
{
    for (auto& e : arr) e *= 2;
}
// 返回array
std::array<int, 4> createArray()
{
    return { 10, 20, 30, 40 };
}
// 整合测试
void demoFunctionPassing()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    processByValue(arr);
    std::cout << "[值传递-外部不变] arr[0]=" << arr[0] << std::endl;
    processByConstRef(arr);
    processByRef(arr);
    std::cout << "[引用传递-修改后] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    auto returned = createArray();
    std::cout << "[函数返回] ";
    for (const auto& e : returned) std::cout << e << " ";
    std::cout << std::endl;
}

2.11 多维数组

模块说明 :演示通过std::array嵌套实现二维、三维数组,替代原生多维数组,保留所有容器接口与类型安全。

2.11.1 二维数组

说明 :演示二维数组(矩阵)的定义与遍历,格式为std::array<std::array<T, 列数>, 行数>,通过范围for可逐层遍历,内存连续且类型安全。

cpp 复制代码
void demoMutiDimensional()
{
    std::array<std::array<int, 3>, 3> matrix = { {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    } };
    std::cout << "[二维数组] " << std::endl;
    for (const auto& row : matrix)
    {
        for (const auto& elem : row)
        {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
}

2.11.2 三维数组

说明 :演示三维数组的嵌套定义,通过三层嵌套std::array实现立体数组存储,语法规则与二维数组一致。

cpp 复制代码
void demoThreeDimensional()
{
    std::array<std::array<std::array<int, 2>, 2>, 2> cube = {{
        {{
            {1, 2}, 
            {3, 4}
        }},
        {{
            {5, 6}, 
            {7, 8}
        }}
    }};
    std::cout << "[三维数组] ";
    for (const auto& plane : cube)
    {
        for (const auto& row : plane)
        {
            for (const auto& elem : row)
            {
                std::cout << elem << " ";
            }
        }
    }
    std::cout << std::endl;
}

2.12 元组接口 (tuple-like interface)

模块说明 :演示std::array的元组式(tuple-like)编译期接口,可在编译期获取数组大小、指定位置元素类型,是元编程与泛型编程的基础。

说明std::tuple_size_v编译期获取数组元素数量;std::tuple_element_t编译期获取指定索引的元素类型,两者均为编译期常量,无运行时开销。

cpp 复制代码
void demoTupleInterface()
{
    std::array<int, 3> arr = { 10, 20, 30 };
    constexpr auto sz = std::tuple_size_v<std::array<int, 3>>;
    std::cout << "[tuple_size] " << sz << std::endl;
    using ElemType = std::tuple_element_t<0, std::array<int, 3>>;
    std::cout << "[tuple_element<0>] type is int: "
        << (std::is_same_v<ElemType, int> ? "true" : "false") << std::endl;
}

2.13 自定义类型数组

模块说明 :演示std::array存储自定义类对象的完整用法,包含基础存储、排序、批量操作,验证自定义类型需满足的运算符要求。

2.13.1 自定义类型

说明 :演示自定义类对象的数组存储与遍历,只要类型支持拷贝构造,即可存入std::array

cpp 复制代码
void demoCustomTypeArray()
{
    std::array<Student, 3> students = {
        Student(1, "Alice", 95.5),
        Student(2, "Bob", 87.0),
        Student(3, "Charlie", 92.3)
    };
    std::cout << "[自定义类型数组] " << std::endl;
    for (const auto& s : students)
    {
        std::cout << "  " << s << std::endl;
    }
}

2.13.2 自定义类型排序

说明 :演示自定义类型数组的排序。std::sort默认使用operator<,示例中Student类的operator<按分数降序定义,因此排序后分数从高到低排列。

cpp 复制代码
void demoCustomTypeSort()
{
    std::array<Student, 3> students = {
        Student(1, "Alice", 95.5),
        Student(2, "Bob", 87.0),
        Student(3, "Charlie", 92.3)
    };
    std::sort(students.begin(), students.end());
    std::cout << "[自定义类型] 排序(按分数排序)" << std::endl;
    for (const auto& s : students)
    {
        std::cout << "  " << s << std::endl;
    }
}

2.13.3 数组批量操作

说明 :演示配合std::for_each对自定义类型数组执行批量修改,统一处理每个对象的成员属性。

cpp 复制代码
void demoPointArrayOperation()
{
    std::array<Point, 4> points = {
        Point(0.0, 0.0), Point(1.0, 1.0),
        Point(2.0, 2.0), Point(3.0, 3.0)
    };
    std::for_each(points.begin(), points.end(), [](Point& p) {
        p.setX(p.getX() * 10);
        p.setY(p.getY() * 10);
    });
    std::cout << "[Point数组批量操作] ";
    for (const auto& p : points) std::cout << p << " ";
    std::cout << std::endl;
}

2.14 constexpr与编译期操作

模块说明 :演示std::array的编译期计算能力。C++20起std::array完全支持constexpr,可在编译期完成数组构造、运算、返回,将计算前置到编译阶段,提升运行时性能。

说明 :包含编译期求和、编译期生成数组两个示例,所有计算均在编译阶段完成,结果作为常量使用,可通过static_assert做编译期校验。

cpp 复制代码
// 计算数组和
constexpr int computeArraySum()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int sum = 0;
    for (size_t i = 0; i < arr.size(); i++)
    {
        sum += arr[i];
    }
    return sum;
}
// 计算平方
constexpr std::array<int, 5> generateSquares()
{
    std::array<int, 5> result{};
    for (size_t i = 0; i < result.size(); i++)
    {
        result[i] = static_cast<int>((i + 1) * (i + 1));
    }
    return result;
}
// constexpr与编译期操作使用
void demoConstexprUsage()
{
    constexpr int sum = computeArraySum();
    static_assert(sum == 15, "sum should be 15");
    std::cout << "[constexpr求和] sum=" << sum << std::endl;
    constexpr auto squares = generateSquares();
    std::cout << "[constexpr生成平方数] ";
    for (const auto& e : squares) std::cout << e << " ";
    std::cout << std::endl;
}

2.15 范围for循环

模块说明 :演示范围for(range-based for)遍历std::array的两种常用写法,是日常开发中最简洁的遍历方式。

说明 :只读遍历使用const auto&避免拷贝;需要修改元素时使用auto&获取引用,直接修改原数组元素。

cpp 复制代码
void demoRangeFor()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[范围for-只读] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[范围for-修改] ";
    for (auto& e : arr) e *= 10;
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

2.16 与std::span配合 (C++20)

模块说明 :演示C++20中std::arraystd::span的协同。std::span是轻量级视图,可无拷贝地引用std::array的全部或部分元素,适合函数参数传递,替代指针+长度的C风格写法。

说明std::array可隐式转换为std::span,也可手动截取数组的一段连续内存生成span,传递过程不发生元素拷贝。

cpp 复制代码
#if _MSVC_LANG >= 202002L
void printSpan(std::span<const int> sp)
{
    std::cout << "[span接收] ";
    for (const auto& e : sp) std::cout << e << " ";
    std::cout << std::endl;
}
#endif
void demoSpanInterop()
{
#if _MSVC_LANG >= 202002L
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    printSpan(arr);
    printSpan(std::span(arr.data() + 1, 3));
#else
    std::cout << "std::span需要C++20支持" << std::endl;
#endif
}

2.17 零大小数组

模块说明 :演示零长度std::arrayN=0)的特性,属于合法语法,主要用于模板编程与边界场景,保证接口一致性。

说明 :零大小数组empty()返回true,begin()end()相等,不存储任何元素,不占用有效数据内存。

cpp 复制代码
void demoZeroSizeArray()
{
    std::array<int, 0> arr;
    std::cout << "[零大小数组] empty=" << (arr.empty() ? "true" : "false")
        << ", size=" << arr.size() << std::endl;
    std::cout << "[零大小数组] begin==end: "
        << (arr.begin() == arr.end() ? "true" : "false") << std::endl;
}

2.18 作为模板参考

模块说明 :演示泛型模板函数接收std::array的写法,通过模板参数推导自动获取元素类型与数组大小,编写通用的数组处理函数。

说明 :示例包含通用打印函数与通用求最大值函数,支持任意元素类型、任意大小的std::array,同时通过static_assert做编译期边界校验。

cpp 复制代码
template <typename T, std::size_t N>
void printArray(const std::array<T, N>& arr)
{
    std::cout << "[模板函数接收] size=" << N << " : ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}
template <typename T, std::size_t N>
T arrayMax(const std::array<T, N>& arr)
{
    static_assert(N > 0, "Array must not be empty");
    T maxVal = arr[0];
    for (std::size_t i = 1; i < N; i++)
    {
        if (arr[i] > maxVal) maxVal = arr[i];
    }
    return maxVal;
}
void demoTemplateUsage()
{
    std::array<int, 4> arr1 = { 3, 1, 4, 1 };
    std::array<double, 3> arr2 = { 3.14, 2.71, 1.41 };
    std::array<std::string, 2> arr3 = { "hello", "world" };
    printArray(arr1);
    printArray(arr2);
    printArray(arr3);
    std::cout << "[模板求最大值] arr1 max=" << arrayMax(arr1) << std::endl;
    std::cout << "[模板求最大值] arr2 max=" << arrayMax(arr2) << std::endl;
}

2.19 与Lambda配合

模块说明 :演示Lambda表达式与std::array的结合用法,包括捕获数组的Lambda、接收数组作为参数的Lambda,实现灵活的就地逻辑封装。

说明:第一种方式通过引用捕获数组,Lambda内部可直接访问/修改数组;第二种方式将数组作为Lambda参数传递,封装可复用的处理逻辑。

cpp 复制代码
void demoLambdaCapture()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    auto printAll = [&arr]() {
        std::cout << "[lambda捕获] ";
        for (const auto& e : arr) std::cout << e << " ";
        std::cout << std::endl;
    };
    printAll();
    auto squareArray = [](std::array<int, 5>& a) {
        for (auto& e : a) e = e * e;
    };
    squareArray(arr);
    std::cout << "[lambda修改后] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

第三章 完整代码

cpp 复制代码
#include<iostream>
#include<array>
#include<algorithm>
#include<numeric>
#include<string>
#include<tuple>
#include<utility>
#include<cassert>
#include<cstring>
#include<type_traits>
#include<functional>
#include<span>

/*
* 非基础类型定义
*/
class Point
{
private:
    double x_;
    double y_;
public:
    Point() : x_(0), y_(0) { }
    Point(double x, double y) : x_(x), y_(y) { }
    bool operator==(const Point& other) const
    {
        return x_ == other.x_ && y_ == other.y_;
    }
    bool operator!=(const Point& other) const
    {
        return !(*this == other);
    }
    bool operator<(const Point& other) const
    {
        if (x_ != other.x_) return x_ < other.x_;
        return y_ < other.y_;
    }
    bool operator<=(const Point& other) const
    {
        return !(other < *this);
    }
    bool operator>(const Point& other) const
    {
        return other < *this;
    }
    bool operator>=(const Point& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const Point& p)
    {
        os << "(" << p.x_ << ", " << p.y_ << ")";
        return os;
    }

    double getX() const { return x_; }
    double getY() const { return y_; }

    void setX(double x) { x_ = x; }
    void setY(double y) { y_ = y; }
};

class Student
{
private:
    int id_;
    std::string name_;
    double score_;
public:
    Student() : id_(0), name_(""), score_(0.0) { }
    Student(int id, const std::string& name, double score)
        : id_(id), name_(name), score_(score) { }
    bool operator==(const Student& other) const
    {
        return id_ == other.id_ && name_ == other.name_ && score_ == other.score_;
    }
    bool operator<(const Student& other) const
    {
        return score_ > other.score_;
    }

    friend std::ostream& operator<<(std::ostream& os, const Student& s)
    {
        os << "Student[" << s.id_ << ", " << s.name_ << ", " << s.score_ << "]";
        return os;
    }

    int getId() const { return id_; }
    std::string getName() const { return name_; }
    double getScore() const { return score_; }

    void setId(int id) { id_ = id; }
    void setName(const std::string& name) { name_ = name; }
    void setScore(double score) { score_ = score; }
};

// ===============================================================

/*
* 1. 声明与初始化
*/

// 1.1 默认初始化
void demoDefaultInit()
{
    std::array<int, 5> arr;
    arr.fill(0);
    std::cout << "[默认初始化] ";
    for (const auto& elem : arr)
    {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

// 1.2 聚合初始化
void demoAggregateInit()
{
    std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
    std::array<int, 5> arr2 = { 10, 20 };
    std::array<std::string, 3> arr3 = { "hello", "world", "cpp" };
    
    std::cout << "[聚合初始化-完全] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[聚合初始化-部分] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[聚合初始化-字符串] ";
    for (const auto& e : arr3) std::cout << e << " ";
    std::cout << std::endl;
}

// 1.3 拷贝初始化
void demoCopyInit()
{
    std::array<int, 4> original = { 1, 2, 3, 4 };
    std::array<int, 4> copied = original;
    std::cout << "[拷贝初始化] ";
    for (const auto& e : copied) std::cout << e << " ";
    std::cout << std::endl;
}

// 1.4 移动初始化
void demoMoveInit()
{
    std::array<std::string, 3> original = { "aaa", "bbb", "ccc" };
    std::array<std::string, 3> moved = std::move(original);
    std::cout << "[移动初始化] ";
    for (const auto& e : moved) std::cout << e << " ";
    std::cout << std::endl;
}

// 1.5 值初始化
void demoValueInit()
{
    std::array<int, 5> arr{};
    std::cout << "[值初始化] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 1.6 自定义类型初始化
void demoClassTypeInit()
{
    std::array<Point, 3> points = {
        Point(1.0, 2.0),
        Point(3.0, 4.0),
        Point(5.0, 6.0)
    };
    std::cout << "[自定义类型初始化] ";
    for (const auto& p : points) std::cout << p << " ";
    std::cout << std::endl;
}

// 1.7 模板推导指引 C++17
void demoDeductionGuide()
{
#if _MSVC_LANG >= 201703L
    // C++14 及以前 ------ 必须写全 std::array<int, 5> arr = {1, 2, 3, 4, 5};
    // C++17 ------ 编译器推导出: std::array<int, 5>
    std::array arr = { 1, 2, 3, 4, 5 };
    std::cout << "[推导指引(C++17)] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
#else
    std::cout << "[推导指引(C++17)] 需要C++17支持" << std::endl;
#endif
}

// 1.8 constexpr初始化
void demoConstexprInit()
{
    constexpr std::array<int, 4> arr = { 10, 20, 30, 40 };
    static_assert(arr.size() == 4, "size must be 4");
    static_assert(arr[0] == 10, "first element must be 10");
    std::cout << "[constexpr初始化]";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 1.9 std::to_array (C++20)
void demoToArray()
{
#if _MSVC_LANG >= 202002L
    int c_arr[] = { 1, 2, 3, 4, 5 };
    auto arr1 = std::to_array(c_arr);
    auto arr2 = std::to_array({ 10, 20, 30 });
    auto arr3 = std::to_array<std::string>({"hello", "world"});
    std::cout << "[std::to_array(C++20)-从C数组] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[std::to_array(C++20)-从初始化列表] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[std::to_array(C++20)-指定类型] ";
    for (const auto& e : arr3) std::cout << e << " ";
    std::cout << std::endl;
#else
    std::cout << "[std::to_array(C++20)] 需要C++20支持" << std::endl;
#endif
}

void demoToArrayMove()
{
#if _MSVC_LANG >= 202002L
    std::string strs[] = { "hello", "world", "cpp" };
    auto arr = std::to_array(std::move(strs));
    std::cout << "[std::to_array(C++20)-移动语义] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
#endif
}

// ===============================================================

/*
* 2. 元素访问
*/

// 2.1 operator[]
void demoOperatorBracket()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[operator[]] arr[0]=" << arr[0] << ", arr[2]=" << arr[2] << std::endl;
    arr[0] = 99;
    std::cout << "[operator[]修改后] arr[0]=" << arr[0] << std::endl;
}

// 2.2 at()
void demoAt()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[at()] arr.at(1)=" << arr.at(1) << std::endl;
    try
    {
        arr.at(10);
    }
    catch (const std::out_of_range& e)
    {
        std::cout << "[at()越界异常] " << e.what() << std::endl;
    }
}

// 2.3 front()
void demoFront()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[front()] " << arr.front() << std::endl;
    arr.front() = 100;
    std::cout << "[front()修改后] " << arr.front() << std::endl;
}

// 2.4 back()
void demoBack()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    std::cout << "[back()} " << arr.back() << std::endl;
    arr.back() = 200;
    std::cout << "[back()修改后] " << arr.back() << std::endl;
}

// 2.5 data()
void demoData()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    int* ptr = arr.data();
    std::cout << "[data()] 通过指针访问: ";
    for (size_t i = 0; i < arr.size(); i++)
    {
        std::cout << ptr[i] << " ";
    }
    std::cout << std::endl;
    std::memset(arr.data(), 0, arr.size() * sizeof(int));
    std::cout << "[data()配合memset] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 2.6 std::get
void demoStdGet()
{
    std::array<int, 4> arr = { 100, 200, 300, 400 };
    std::cout << "[std::get<0>] " << std::get<0>(arr) << std::endl;
    std::cout << "[std::get<2>] " << std::get<2>(arr) << std::endl;
    std::get<1>(arr) = 999;
    std::cout << "[std::get修改后] arr[1]=" << arr[1] << std::endl;
}

// ===============================================================

/*
* 3. 迭代器操作
*/

// 3.1 begin / end
void demoBeginEnd()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5 };
    std::cout << "[begin/end正向遍历] ";
    for (auto it = arr.begin(); it != arr.end(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

// 3.2 cbegin / cend
void demoCBeginCEnd()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[cbegin/cend常量遍历] ";
    for (auto it = arr.cbegin(); it != arr.cend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

// 3.3 rbegin / rend
void demoRbeginRend()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[rbegin/rend反向遍历] ";
    for (auto it = arr.rbegin(); it != arr.rend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

// 3.4 crbegin / crend
void demoCRbeginCRend()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[crbegin/crend常量反向遍历] ";
    for (auto it = arr.crbegin(); it != arr.crend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
}

// 3.5 iterator arithmetic
void demoIteratorArithmetic()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    auto it = arr.begin();
    std::cout << "[迭代器算数] it+2 -> " << *(it + 2) << std::endl;
    std::cout << "[迭代器距离] end - begin = " << (arr.end() - arr.begin()) << std::endl;
    auto it2 = arr.begin() + 3;
    std::cout << "[迭代器比较] it < it2 : " << (it < it2 ? "true" : "false") << std::endl;
}

// ===============================================================

/*
* 4. 容量查询
*/

// 4.1 size
void demoSize()
{
    std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
    std::cout << "[size()] " << arr.size() << std::endl;
}

// 4.2 max_size
void demoMaxSize()
{
    std::array<int, 7> arr = { 1, 2, 3, 4, 5, 6, 7 };
    std::cout << "[max_size()] " << arr.max_size() << std::endl;
}

// 4.3 empty
void demoEmpty()
{
    std::array<int, 5> arr1 = { 1, 2, 3, 4, 5 };
    std::array<int, 0> arr2 = {};
    std::cout << "[empty()] arr1: " << (arr1.empty() ? "true" : "false") << std::endl;
    std::cout << "[empty()] arr2(size=0): " << (arr2.empty() ? "true" : "false") << std::endl;
}

// ===============================================================

/*
* 5. 修改操作
*/

// 5.1 fill
void demoFill()
{
    std::array<int, 5> arr;
    arr.fill(42);
    std::cout << "[fill(42)] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 5.2 swap
void demoSwap()
{
    std::array<int, 3> arr1 = { 1, 2, 3 };
    std::array<int, 3> arr2 = { 10, 20, 30 };
    arr1.swap(arr2);
    std::cout << "[swap后 arr1] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[swap后 arr2] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}

void demoStdSwap()
{
    std::array<int, 3> arr1 = { 1, 2, 3 };
    std::array<int, 3> arr2 = { 10, 20, 30 };
    std::swap(arr1, arr2);
    std::cout << "[std::swap后 arr1] ";
    for (const auto& e : arr1) std::cout << e << " ";
    std::cout << std::endl;
}

// 5.3 赋值
void demoAssignment()
{
    std::array<int, 4> arr1 = { 1, 2, 3, 4 };
    std::array<int, 4> arr2;
    arr2 = arr1;
    std::cout << "[拷贝赋值] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}

void demoMoveAssignment()
{
    std::array<std::string, 3> arr1 = { "hello", "world", "cpp" };
    std::array<std::string, 3> arr2;
    arr2 = std::move(arr1);
    std::cout << "[移动赋值] ";
    for (const auto& e : arr2) std::cout << e << " ";
    std::cout << std::endl;
}
 
// ===============================================================

/*
* 6. 比较操作
*/

// 6.1 比较操作符
void demoComparisonOperators()
{
    std::array<int, 3> a = { 1, 2, 3 };
    std::array<int, 3> b = { 1, 2, 3 };
    std::array<int, 3> c = { 1, 2, 4 };
    std::array<int, 3> d = { 1, 2, 2 };
    std::cout << "[==] a == b : " << (a == b ? "true" : "false") << std::endl;
    std::cout << "[!=] a != b : " << (a != b ? "true" : "false") << std::endl;
    std::cout << "[<] a < c : " << (a < c ? "true" : "false") << std::endl;
    std::cout << "[>] a > d : " << (a > d ? "true" : "false") << std::endl;
    std::cout << "[<=] a <= b : " << (a <= b ? "true" : "false") << std::endl;
    std::cout << "[>=] a >= c : " << (a >= c ? "true" : "false") << std::endl;
}

void demoThreeWayComparison()
{
#if _MSVC_LANG >= 202002L
    std::array<int, 3> a = { 1, 2, 3 };
    std::array<int, 3> b = { 1, 2, 4 };
    auto result = (a <=> b);
    if (result < 0)
    {
        std::cout << "[<=>] a < b" << std::endl;
    }
    else if (result > 0)
    {
        std::cout << "[<=>] a > b" << std::endl;
    }
    else
    {
        std::cout << "[<=>] a == b" << std::endl;
    }
#else
    std::cout << "[<=>] 需要C++20支持" << std::endl;
#endif
}

// ===============================================================

/*
* 7. 与STL算法配合
*/

// 7.1 sort
void demoAlgoSort()
{
    std::array<int, 6> arr = { 5, 3, 1, 4, 6, 2 };
    std::sort(arr.begin(), arr.end());
    std::cout << "[sort升序] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    std::sort(arr.begin(), arr.end(), std::greater<int>());
    std::cout << "[sort降序] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.2 find
void demoAlgoFind()
{
    std::array<int, 5> arr = { 10, 20, 30, 40, 50 };
    auto it = std::find(arr.begin(), arr.end(), 30);
    if (it != arr.end())
    {
        std::cout << "[find] 找到30, 索引=" << std::distance(arr.begin(), it) << std::endl;
    }
    auto it2 = std::find(arr.begin(), arr.end(), 99);
    if (it2 == arr.end())
    {
        std::cout << "[find] 未找到99" << std::endl;
    }
}

// 7.3 accumulate
void demoAlgoAccumulate()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int sum = std::accumulate(arr.begin(), arr.end(), 0);
    std::cout << "[accumulate] sum=" << sum << std::endl;
}

// 7.4 minmax
void demoAlgoMinMax()
{
#if _MSVC_LANG >= 201703L
    std::array<int, 5> arr = { 3, 1, 4, 1, 5 };
    auto [minIt, maxIt] = std::minmax_element(arr.begin(), arr.end());
    std::cout << "[minmax_element] min=" << *minIt << ", max=" << *maxIt << std::endl;
#endif
}

// 7.5 count
void demoAlgoCount()
{
    std::array<int, 8> arr = { 1, 2, 2, 3, 2, 4, 2, 5 };
    auto cnt = std::count(arr.begin(), arr.end(), 2);
    std::cout << "[count] 2出现了 " << cnt << " 次" << std::endl;
}

// 7.6 transform
void demoAlgoTransform()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::array<int, 5> result;
    std::transform(arr.begin(), arr.end(), result.begin(),
        [](int x) { return x * x; }
    );
    std::cout << "[transform平方] ";
    for (const auto& e : result) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.7 for_each
void demoAlgoForEach()
{
    std::array<std::string, 3> arr = { "hello", "world", "cpp" };
    std::cout << "[for_each]";
    std::for_each(arr.begin(), arr.end(), [](const std::string& s) { std::cout << s << " "; });
    std::cout << std::endl;
}

// 7.8 reverse
void demoAlgoReverse()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::reverse(arr.begin(), arr.end());
    std::cout << "[reverse] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.9 copy
void demoAlgoCopy()
{
    std::array<int, 5> src = { 1, 2, 3, 4, 5 };
    std::array<int, 5> dst{};
    std::copy(src.begin(), src.end(), dst.begin());
    std::cout << "[copy] ";
    for (const auto& e : dst) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.10 replace
void demoAlgoReplace()
{
    std::array<int, 6> arr = { 1, 2, 3, 2, 4, 2 };
    std::replace(arr.begin(), arr.end(), 2, 99);
    std::cout << "[replace] 2->99: ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.11 all_of / any_of / none_of
void demoAlgoAnyAllNone()
{
    std::array<int, 5> arr = { 2, 4, 6, 8, 10 };
    bool allEven = std::all_of(arr.begin(), arr.end(), [](int x) { return x % 2 == 0; });
    bool anyGt5 = std::any_of(arr.begin(), arr.end(), [](int x) { return x > 5; });
    bool nonNeg = std::none_of(arr.begin(), arr.end(), [](int x) { return x < 0; });
    std::cout << "[all_of全偶数] " << (allEven ? "true" : "false") << std::endl;
    std::cout << "[any_of有>5] " << (anyGt5 ? "true" : "false") << std::endl;
    std::cout << "[none_of无负数] " << (nonNeg ? "true" : "false") << std::endl;
}

// 7.12 binary_search
void demoAlgoBinarySearch()
{
    std::array<int, 6> arr = { 1, 3, 5, 7, 9, 11 };
    bool found = std::binary_search(arr.begin(), arr.end(), 7);
    std::cout << "[binary_search] 找7 " << (found ? "true" : "false") << std::endl;
    auto lb = std::lower_bound(arr.begin(), arr.end(), 5);
    auto ub = std::upper_bound(arr.begin(), arr.end(), 5);
    std::cout << "[lower_bound(5)] 索引=" << std::distance(arr.begin(), lb) << std::endl;
    std::cout << "[upper_bound(5)] 索引=" << std::distance(arr.begin(), ub) << std::endl;
}

// 7.13 unique
void demoAlgoUnique()
{
    std::array<int, 7> arr = { 1, 1, 2, 2, 3, 3, 3 };
    auto newEnd = std::unique(arr.begin(), arr.end());
    std::cout << "[unique]后 ";
    for (auto it = arr.begin(); it != arr.end(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "(去重后有效元素数=" << std::distance(arr.begin(), newEnd) << ")" << std::endl;
}

// 7.14 rotate
void demoAlgoRotate()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::rotate(arr.begin(), arr.begin() + 2, arr.end());
    std::cout << "[rotate]左旋2位 ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.15 iota
void demoAlgoIota()
{
    std::array<int, 5> arr;
    std::iota(arr.begin(), arr.end(), 1);
    std::cout << "[iota]从1开始 ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 7.16 partial_sum
void demoAlgoPartialSum()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::array<int, 5> result;
    std::partial_sum(arr.begin(), arr.end(), result.begin());
    std::cout << "[partial_sum]前缀和 ";
    for (const auto& e : result) std::cout << e << " ";
    std::cout << std::endl;
}

// ===============================================================

/*
* 8. 结构化绑定 C++17
*/

// 8.1 引用修改
void demoStructedBindings()
{
#if _MSVC_LANG >= 201703L
    std::array<int, 3> arr = { 100, 200, 300 };
    auto [a, b, c] = arr;
    std::cout << "[结构化绑定] a=" << a << ", b=" << b << ", c=" << c << std::endl;
    auto& [x, y, z] = arr;
    x = 999;
    std::cout << "[结构化绑定-引用修改] arr[0]=" << arr[0] << std::endl;
#else
    std::cout << "[结构化绑定] 需要支持C++17" << std::endl;
#endif
}

// 8.2 const引用
void demoStructedBindingsConst()
{
#if _MSVC_LANG >= 201703L
    const std::array<std::string, 3> arr = { "alpha", "beta", "gamma" };
    const auto& [first, second, third] = arr;
    std::cout << "[结构化绑定-const引用] " << first << ", " << second << ", " << third << std::endl;
#else
    std::cout << "[结构化绑定] 需要支持C++17" << std::endl;
#endif
}

// ===============================================================

/*
* 9. 函数传参与返回
*/

// 9.1 值传递-内部修改
void processByValue(std::array<int, 5> arr)
{
    arr[0] = 999;
    std::cout << "[值传递-内部修改] arr[0]=" << arr[0] << std::endl;
}

// 9.2 const引用传递
void processByConstRef(const std::array<int, 5>& arr)
{
    std::cout << "[const引用传递] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// 9.3 引用传递
void processByRef(std::array<int, 5>& arr)
{
    for (auto& e : arr) e *= 2;
}

// 9.4 返回array
std::array<int, 4> createArray()
{
    return { 10, 20, 30, 40 };
}

// 9. 整合测试
void demoFunctionPassing()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    processByValue(arr);
    std::cout << "[值传递-外部不变] arr[0]=" << arr[0] << std::endl;
    processByConstRef(arr);
    processByRef(arr);
    std::cout << "[引用传递-修改后] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    auto returned = createArray();
    std::cout << "[函数返回] ";
    for (const auto& e : returned) std::cout << e << " ";
    std::cout << std::endl;
}

// ===============================================================

/*
* 10. 多维数组
*/

// 10.1 二维数组
void demoMutiDimensional()
{
    std::array<std::array<int, 3>, 3> matrix = { {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    } };
    std::cout << "[二维数组] " << std::endl;
    for (const auto& row : matrix)
    {
        for (const auto& elem : row)
        {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
}

// 10.2 三维数组
void demoThreeDimensional()
{
    std::array<std::array<std::array<int, 2>, 2>, 2> cube = {{
        {{
            {1, 2}, 
            {3, 4}
        }},
        {{
            {5, 6}, 
            {7, 8}
        }}
    }};
    std::cout << "[三维数组] ";
    for (const auto& plane : cube)
    {
        for (const auto& row : plane)
        {
            for (const auto& elem : row)
            {
                std::cout << elem << " ";
            }
        }
    }
    std::cout << std::endl;
}

// ===============================================================

/*
* 11. 元组接口 (tuple-like interface)
*/
void demoTupleInterface()
{
    std::array<int, 3> arr = { 10, 20, 30 };
    constexpr auto sz = std::tuple_size_v<std::array<int, 3>>;
    std::cout << "[tuple_size] " << sz << std::endl;
    using ElemType = std::tuple_element_t<0, std::array<int, 3>>;
    std::cout << "[tuple_element<0>] type is int: "
        << (std::is_same_v<ElemType, int> ? "true" : "false") << std::endl;
}

// ===============================================================

/*
* 12. 自定义类型数组
*/

// 12.1 自定义类型
void demoCustomTypeArray()
{
    std::array<Student, 3> students = {
        Student(1, "Alice", 95.5),
        Student(2, "Bob", 87.0),
        Student(3, "Charlie", 92.3)
    };
    std::cout << "[自定义类型数组] " << std::endl;
    for (const auto& s : students)
    {
        std::cout << "  " << s << std::endl;
    }
}

// 12.2 自定义类型排序
void demoCustomTypeSort()
{
    std::array<Student, 3> students = {
        Student(1, "Alice", 95.5),
        Student(2, "Bob", 87.0),
        Student(3, "Charlie", 92.3)
    };
    std::sort(students.begin(), students.end());
    std::cout << "[自定义类型] 排序(按分数排序)" << std::endl;
    for (const auto& s : students)
    {
        std::cout << "  " << s << std::endl;
    }
}

// 12.3 数组批量操作
void demoPointArrayOperation()
{
    std::array<Point, 4> points = {
        Point(0.0, 0.0), Point(1.0, 1.0),
        Point(2.0, 2.0), Point(3.0, 3.0)
    };
    std::for_each(points.begin(), points.end(), [](Point& p) {
        p.setX(p.getX() * 10);
        p.setY(p.getY() * 10);
    });
    std::cout << "[Point数组批量操作] ";
    for (const auto& p : points) std::cout << p << " ";
    std::cout << std::endl;
}

// ===============================================================

/*
* 13. constexpr与编译期操作
*/

// 13.1 计算数组和
constexpr int computeArraySum()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    int sum = 0;
    for (size_t i = 0; i < arr.size(); i++)
    {
        sum += arr[i];
    }
    return sum;
}

// 13.2 计算平方
constexpr std::array<int, 5> generateSquares()
{
    std::array<int, 5> result{};
    for (size_t i = 0; i < result.size(); i++)
    {
        result[i] = static_cast<int>((i + 1) * (i + 1));
    }
    return result;
}

// 13. constexpr与编译期操作使用
void demoConstexprUsage()
{
    constexpr int sum = computeArraySum();
    static_assert(sum == 15, "sum should be 15");
    std::cout << "[constexpr求和] sum=" << sum << std::endl;
    constexpr auto squares = generateSquares();
    std::cout << "[constexpr生成平方数] ";
    for (const auto& e : squares) std::cout << e << " ";
    std::cout << std::endl;
}

// ===============================================================

/*
* 14. 范围for循环
*/
void demoRangeFor()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << "[范围for-只读] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
    std::cout << "[范围for-修改] ";
    for (auto& e : arr) e *= 10;
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// ===============================================================

/*
* 15. 与std::span配合 (C++20)
*/
#if _MSVC_LANG >= 202002L
void printSpan(std::span<const int> sp)
{
    std::cout << "[span接收] ";
    for (const auto& e : sp) std::cout << e << " ";
    std::cout << std::endl;
}
#endif

void demoSpanInterop()
{
#if _MSVC_LANG >= 202002L
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    printSpan(arr);
    printSpan(std::span(arr.data() + 1, 3));
#else
    std::cout << "std::span需要C++20支持" << std::endl;
#endif
}

// ===============================================================

/*
* 16. 零大小数组
*/
void demoZeroSizeArray()
{
    std::array<int, 0> arr;
    std::cout << "[零大小数组] empty=" << (arr.empty() ? "true" : "false")
        << ", size=" << arr.size() << std::endl;
    std::cout << "[零大小数组] begin==end: "
        << (arr.begin() == arr.end() ? "true" : "false") << std::endl;
}

// ===============================================================

/*
* 17. 作为模板参考
*/
template <typename T, std::size_t N>
void printArray(const std::array<T, N>& arr)
{
    std::cout << "[模板函数接收] size=" << N << " : ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

template <typename T, std::size_t N>
T arrayMax(const std::array<T, N>& arr)
{
    static_assert(N > 0, "Array must not be empty");
    T maxVal = arr[0];
    for (std::size_t i = 1; i < N; i++)
    {
        if (arr[i] > maxVal) maxVal = arr[i];
    }
    return maxVal;
}

void demoTemplateUsage()
{
    std::array<int, 4> arr1 = { 3, 1, 4, 1 };
    std::array<double, 3> arr2 = { 3.14, 2.71, 1.41 };
    std::array<std::string, 2> arr3 = { "hello", "world" };
    printArray(arr1);
    printArray(arr2);
    printArray(arr3);
    std::cout << "[模板求最大值] arr1 max=" << arrayMax(arr1) << std::endl;
    std::cout << "[模板求最大值] arr2 max=" << arrayMax(arr2) << std::endl;
}

// ===============================================================

/*
* 18. 与Lambda配合
*/
void demoLambdaCapture()
{
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    auto printAll = [&arr]() {
        std::cout << "[lambda捕获] ";
        for (const auto& e : arr) std::cout << e << " ";
        std::cout << std::endl;
    };
    printAll();
    auto squareArray = [](std::array<int, 5>& a) {
        for (auto& e : a) e = e * e;
    };
    squareArray(arr);
    std::cout << "[lambda修改后] ";
    for (const auto& e : arr) std::cout << e << " ";
    std::cout << std::endl;
}

// ===============================================================

int main()
{
    std::cout << "========== 1. 声明与初始化 ==========" << std::endl;
    demoDefaultInit();
    demoAggregateInit();
    demoCopyInit();
    demoMoveInit();
    demoValueInit();
    demoClassTypeInit();
    demoDeductionGuide();
    demoConstexprInit();
    demoToArray();
    demoToArrayMove();

    std::cout << "\n========== 2. 元素访问 ==========" << std::endl;
    demoOperatorBracket();
    demoAt();
    demoFront();
    demoBack();
    demoData();
    demoStdGet();
    
    std::cout << "\n========== 3. 迭代器操作 ==========" << std::endl;
    demoBeginEnd();
    demoCBeginCEnd();
    demoRbeginRend();
    demoCRbeginCRend();
    demoIteratorArithmetic();
    
    std::cout << "\n========== 4. 容量查询 ==========" << std::endl;
    demoSize();
    demoMaxSize();
    demoEmpty();

    std::cout << "\n========== 5. 修改操作 ==========" << std::endl;
    demoFill();
    demoSwap();
    demoStdSwap();
    demoAssignment();
    demoMoveAssignment();

    std::cout << "\n========== 6. 比较操作 ==========" << std::endl;
    demoComparisonOperators();
    demoThreeWayComparison();

    std::cout << "\n========== 7. 与STL算法配合 ==========" << std::endl;
    demoAlgoSort();
    demoAlgoFind();
    demoAlgoAccumulate();
    demoAlgoMinMax();
    demoAlgoCount();
    demoAlgoTransform();
    demoAlgoForEach();
    demoAlgoReverse();
    demoAlgoCopy();
    demoAlgoReplace();
    demoAlgoAnyAllNone();
    demoAlgoBinarySearch();
    demoAlgoUnique();
    demoAlgoRotate();
    demoAlgoIota();
    demoAlgoPartialSum();

    std::cout << "\n========== 8. 结构化绑定 ==========" << std::endl;
    demoStructedBindings();
    demoStructedBindingsConst();

    std::cout << "\n========== 9. 函数传参与返回 ==========" << std::endl;
    demoFunctionPassing();

    std::cout << "\n========== 10. 多维数组 ==========" << std::endl;
    demoMutiDimensional();
    demoThreeDimensional();

    std::cout << "\n========== 11. 元组接口 (tuple-like interface) ==========" << std::endl;
    demoTupleInterface();

    std::cout << "\n========== 12. 自定义类型数组 ==========" << std::endl;
    demoCustomTypeArray();
    demoCustomTypeSort();
    demoPointArrayOperation();

    std::cout << "\n========== 13. constexpr ==========" << std::endl;
    demoConstexprUsage();

    std::cout << "\n========== 14. 范围for循环 ==========" << std::endl;
    demoRangeFor();
    
    std::cout << "\n========== 15. 与std::span配合 (C++20) ==========" << std::endl;
    demoSpanInterop();
    
    std::cout << "\n========== 16. 零大小数组 ==========" << std::endl;
    demoZeroSizeArray();
    
    std::cout << "\n========== 17. 作为模板参考 ==========" << std::endl;
    demoTemplateUsage();
    
    std::cout << "\n========== 18. 与lambda配合 ==========" << std::endl;
    demoLambdaCapture();
    
    return 0;
}
相关推荐
choumin1 小时前
结构型模式——组合模式
c++·设计模式·组合模式·结构型模式
奶糖 肥晨1 小时前
mac系统中Java项目环境配置与问题解决全记录| 项目构建篇:Maven编译与打包
java·macos·maven
wuyk5551 小时前
66.嵌入式C语言进阶:共用体(Union)实战指南——单片机内存省一半的神级技巧
c语言·开发语言·stm32·单片机·嵌入式硬件
怪奇云呼军2 小时前
闪电智能 Voice Agent 怎样根据语速、停顿和追问方式切换话术?策略引擎拆解
开发语言·人工智能·网络协议·算法·语音识别·web app
努力努力再努力wz2 小时前
【分布式系统与 RPC 框架系列】从单机瓶颈到远程调用:一文理解分布式架构与 RPC 原理
linux·网络·c++·分布式·网络协议·rpc·架构
万亿少女的梦1682 小时前
基于Spring Boot的乐助在线助农系统设计与实现
java·spring boot·mysql·敏感词过滤·助农系统
Ivanqhz2 小时前
Rust parse() 浅析
开发语言·后端·rust
神仙别闹2 小时前
基于C++实现(控制台)景区旅游管理系统
开发语言·c++·旅游
唐青枫2 小时前
Java Undertow 实战指南:从轻量 Web Server 到 Spring Boot 嵌入式容器
java