当前位置: 首页 > news >正文

C++11 <array>从入门到精通

文章目录

    • 一、引言
    • 二、std::array简介
      • 2.1 定义
      • 2.2 特点
      • 2.3 与C风格数组的区别
    • 三、std::array的基本操作
      • 3.1 包含头文件
      • 3.2 声明与初始化
        • 3.2.1 声明
        • 3.2.2 初始化
      • 3.3 访问元素
      • 3.4 遍历数组
        • 3.4.1 基于范围的for循环
        • 3.4.2 迭代器遍历
    • 四、std::array的常用成员函数
      • 4.1 `size()`
      • 4.2 `front()`和`back()`
      • 4.3 `data()`
      • 4.4 `fill(const T& value)`
      • 4.5 `swap(array& other)`
    • 五、std::array的高级应用
      • 5.1 与STL算法结合使用
      • 5.2 多维数组
    • 六、std::array的优缺点和适用场景
      • 6.1 优点
      • 6.2 缺点
      • 6.3 适用场景
    • 七、总结

一、引言

在C++编程中,数组是一种非常基础且重要的数据结构,它可以存储一组相同类型的元素。在C++11标准之前,开发者通常使用C风格数组来处理数组数据,但C风格数组存在一些问题,比如无法直接进行对象赋值、无法直接拷贝、数组名会退化为指针等,这些问题给开发带来了一定的困扰。为了解决这些问题,C++11标准引入了<array>头文件,提供了std::array容器,它是对C风格数组的改进和封装,具有更多的功能和安全性。本文将详细介绍std::array的相关知识,帮助小白从入门到精通。

二、std::array简介

2.1 定义

std::array是C++11标准库提供的一个固定大小的容器,用于存储特定类型的元素序列。它定义在<array>头文件中,是一个模板类,其基本定义如下:

template <typename T, std::size_t N>
class array;

其中,T表示数组中元素的类型,N表示数组的大小(即元素的个数)。

2.2 特点

  • 固定大小std::array的大小在创建时就已经确定,并且之后不能再改变。这种固定大小的特性使得std::array在内存使用上是高效的,因为它不需要动态分配内存或管理内存大小的变化。同时,由于其大小在编译时就已知,编译器可以进行一些优化,提高代码的执行效率。
  • 类型安全std::array强制类型检查,避免了C语言数组的类型不安全问题。它提供了at()函数来访问元素,同时提供边界检查以避免越界错误。
  • 内存连续std::array的元素在内存中是连续存储的,这使得它可以高效地访问元素。
  • 标准容器接口std::array提供了与std::vector类似的接口,如size()at()front()back()等,使得对数组的操作更加便捷和安全。

2.3 与C风格数组的区别

比较项std::arrayC风格数组
大小固定大小,在编译时确定大小可以是动态的,在运行时可以根据需要分配和调整
内存分配对象通常在栈上分配,生命周期与创建它的作用域相同可以在栈上或堆上分配,取决于数组的声明方式
安全性和边界检查提供边界检查,使用at()函数访问元素时,如果索引超出范围,程序会抛出异常不提供边界检查,程序员必须自己确保不会访问数组的非法区域
使用便捷性提供了许多便利的成员函数和迭代器,操作更加简单和直观操作相对较为基础,没有提供这些便利的函数和迭代器
与STL算法的兼容性作为STL容器,与STL算法完美兼容虽然也可以与一些STL算法结合使用,但通常需要额外的处理或转换

C++11 array与C风格数组对比

三、std::array的基本操作

3.1 包含头文件

要使用std::array,需要包含头文件<array>

#include <array>

3.2 声明与初始化

3.2.1 声明

声明一个std::array对象时,需要指定数组中的元素类型和数组的大小。声明的基本语法如下:

std::array<T, N> array_name;

其中,T是数组中元素的类型,N是数组的大小,必须是一个非负整数。

3.2.2 初始化
  • 默认值初始化:如果不提供任何初始值,std::array中的元素将使用其类型的默认值进行初始化。
std::array<int, 5> myArray; // 所有元素将被初始化为随机值
  • 列表初始化:可以使用花括号{}内的元素列表来初始化std::array。元素的数量必须与数组大小相匹配。
std::array<int, 5> myArray1 = {1, 2, 3, 4, 5};
std::array<int, 5> myArray2 {1, 2, 3, 4, 5};
  • 使用std::fill:可以使用std::fill函数来设置std::array中所有元素的值。
std::array<int, 5> myArray;
std::fill(myArray.begin(), myArray.end(), 0); // 所有元素设置为0

3.3 访问元素

可以使用下标操作符[]或者at()成员函数来访问std::array中的元素。at()函数会进行边界检查,如果索引越界,会抛出std::out_of_range异常。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};std::cout << "arr[0] = " << arr[0] << std::endl; // 使用下标操作符std::cout << "arr.at(2) = " << arr.at(2) << std::endl; // 使用at()函数try {std::cout << arr.at(5) << std::endl; // 超出范围,抛出异常} catch (const std::out_of_range& e) {std::cout << "Exception: " << e.what() << std::endl;}return 0;
}

C++11 array代码示例

3.4 遍历数组

std::array支持基于范围的for循环和迭代器,使得遍历元素变得非常方便。

3.4.1 基于范围的for循环
#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};for (const auto& elem : arr) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}
3.4.2 迭代器遍历
#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};for (auto it = arr.begin(); it != arr.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

四、std::array的常用成员函数

4.1 size()

返回数组的大小,即元素的数量。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};std::cout << "Array size: " << arr.size() << std::endl;return 0;
}

4.2 front()back()

front()返回数组的第一个元素的引用,back()返回数组的最后一个元素的引用。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};std::cout << "First element: " << arr.front() << std::endl;std::cout << "Last element: " << arr.back() << std::endl;return 0;
}

4.3 data()

返回一个指向数组首个元素的指针。利用该指针,可以实现复制容器中所有元素等类似功能。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {1, 2, 3, 4, 5};int* ptr = arr.data();for (int i = 0; i < arr.size(); ++i) {std::cout << *(ptr + i) << " ";}std::cout << std::endl;return 0;
}

4.4 fill(const T& value)

value这个值赋值给容器中的每个元素。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr;arr.fill(10);for (const auto& elem : arr) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

4.5 swap(array& other)

交换两个数组的内容,但前提是它们具有相同的长度和类型。

#include <iostream>
#include <array>int main() {std::array<int, 5> arr1 = {1, 2, 3, 4, 5};std::array<int, 5> arr2 = {5, 4, 3, 2, 1};arr1.swap(arr2);for (const auto& elem : arr1) {std::cout << elem << " ";}std::cout << std::endl;for (const auto& elem : arr2) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

五、std::array的高级应用

5.1 与STL算法结合使用

由于std::array完全兼容STL(标准模板库),可以与其他STL算法和容器类无缝协作。例如,可以使用std::sort对数组进行排序。

#include <iostream>
#include <array>
#include <algorithm>int main() {std::array<int, 5> arr = {5, 3, 1, 4, 2};std::sort(arr.begin(), arr.end());for (const auto& elem : arr) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

C++11 array高级应用

5.2 多维数组

可以使用std::array创建多维数组。例如,创建一个二维数组:

#include <iostream>
#include <array>int main() {std::array<std::array<int, 3>, 2> arr = {{ {1, 2, 3}, {4, 5, 6} }};for (const auto& row : arr) {for (const auto& elem : row) {std::cout << elem << " ";}std::cout << std::endl;}return 0;
}

六、std::array的优缺点和适用场景

6.1 优点

  • 类型安全std::array的大小是类型的一部分,因此不能创建大小不匹配的std::array对象,避免了一些潜在的错误。
  • 性能:由于大小在编译时已知,编译器可以对std::array进行更多的优化,提高代码的执行效率。
  • 接口丰富std::array提供了许多有用的成员函数,如fill()swap()等,这些函数让数组的操作更加便捷。

6.2 缺点

  • 固定大小std::array的大小在编译时就已确定,无法动态增加或减少元素,不适合需要动态调整数组大小的场景。
  • 初始化:如果std::array在全局或命名空间作用域中定义,并且没有显式初始化,则所有元素都将被零初始化,这在某些情况下可能是不必要的或不方便的。

6.3 适用场景

当需要使用固定大小的数组,并且对性能和安全性有较高要求时,std::array是一个很好的选择。例如,在数学和科学计算中,表示向量和矩阵;在图形编程中,表示像素数据、纹理和颜色等。

七、总结

std::array是C++11引入的一个非常有用的容器,它结合了C风格数组的性能和可访问性以及容器的优点,提供了一种更安全、更灵活的方式来处理固定大小的数组。通过本文的介绍,相信小白们已经对std::array有了更深入的了解,能够在实际编程中熟练使用它。希望大家在使用std::array的过程中,能够充分发挥其优势,提高编程效率和代码质量。

http://www.lqws.cn/news/488755.html

相关文章:

  • Git新建分支并同步到远程
  • 终端创建虚拟环境
  • Blazor-内置输入组件
  • 华为云 Flexus+DeepSeek 征文|增值税发票智能提取小工具:基于大模型的自动化信息解析实践
  • 2025 年焊接相机十大品牌测评:抗光耐高温解决方案深度解析
  • Three.js入门第一步:两种方式搭建你的3D项目[特殊字符]️
  • CentOS 上安装snmp
  • mac隐藏文件现身快捷键
  • 从 0 到 1 实现 C++ string 类:深入理解动态字符串的底层机制--《Hello C++ Wrold!》(11)--(C/C++)
  • 编程实践:sigmastar330 调用IVE图像处理加速
  • Linux密码校验机制深度剖析:从shadow文件到crypt加密
  • PicHome结合容器化与内网穿透实现跨平台影像管理
  • 使用docx4j 实现word转pdf(linux乱码处理)
  • 支持java8的kafka版本
  • Halcon ——— OCR字符提取与多类型识别技术详解
  • Python Arrow 库详解:更智能的日期时间处理
  • 北京他山科技:全球首款AI触觉感知芯片破局者
  • 七八章习题测试
  • 半导体行业中的专用标准产品ASSP是什么?
  • SRS(Simple Realtime Server) 开源直播/双录服务器
  • 商品中心—11.商品B端搜索系统的实现文档二
  • 嵌入式系统内核镜像相关(六)
  • 网络/信号/电位跟踪
  • Actuator内存泄露及利用Swagger未授权自动化测试实现
  • 【软考高级系统架构论文】论面向方面的编程技术及其应用
  • 班翎流程平台 | 逐级审批支持多种选择模式
  • OpenHarmony中默认export 添加环境变量
  • 用html实现数字生命
  • 日志技术-Logback入门程序
  • Life:Internship in OnSea Day 1