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

文章目录

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

一、引言

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

二、std::array简介

2.1 定义

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

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

三、std::array的基本操作

3.1 包含头文件

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

cpp 复制代码
#include <array>

3.2 声明与初始化

3.2.1 声明

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

cpp 复制代码
std::array<T, N> array_name;

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

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

3.3 访问元素

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

cpp 复制代码
#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;
}

3.4 遍历数组

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

3.4.1 基于范围的for循环
cpp 复制代码
#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 迭代器遍历
cpp 复制代码
#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()

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

cpp 复制代码
#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()返回数组的最后一个元素的引用。

cpp 复制代码
#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()

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

cpp 复制代码
#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这个值赋值给容器中的每个元素。

cpp 复制代码
#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)

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

cpp 复制代码
#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对数组进行排序。

cpp 复制代码
#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;
}

5.2 多维数组

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

cpp 复制代码
#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的过程中,能够充分发挥其优势,提高编程效率和代码质量。

相关推荐
wjs20249 分钟前
DOM CDATA
开发语言
Tingjct10 分钟前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
猷咪36 分钟前
C++基础
开发语言·c++
IT·小灰灰38 分钟前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧39 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q40 分钟前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳040 分钟前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾40 分钟前
php 对接deepseek
android·开发语言·php
CSDN_RTKLIB43 分钟前
WideCharToMultiByte与T2A
c++
2601_9498683644 分钟前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter