第一章 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 非基础类型定义
模块说明 :本部分定义了Point和Student两个自定义类,均完整重载了相等比较、大小比较与流输出运算符,用于后续演示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;
}
2.8.12 binary_search
说明 :演示有序数组的二分查找相关算法: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::array与std::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::array(N=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;
}