菜鸟笔记
提升您的技术认知

std::array

array

  • c++11 封装了相关的数组模板类,不同于 C 风格数组,它不会自动退化成 T* 类型,它能作为聚合类型聚合初始化
  • std::array 是封装固定大小数组的容器,数组元素下标索引从 0 开始
// 模板类定义
template<typename _Tp, std::size_t _Nm> 
struct array{...};

// 数组元素个数为 0,访问时行为未定义
std::array<int, 0> arr;
// 常见初始化方法
int main()
{
    const int SIZE = 5;
    auto Print = [](const std::array<int, SIZE> &arr){
        std::cout << "arr value : \t";
        for (const auto &val : arr) {
            std::cout << val << "\t";
        }
        std::cout << "\n";
    };
    // 初始化容器
    std::array<int, SIZE> arr;
    Print(arr);  //  未初始化值为随机值
    for (int i = 0; i < SIZE; ++i) {  // 先定义,后初始化
        arr[i] = i;
    }
    Print(arr);
    std::array<int, SIZE> arr1{2,3,4,5,6};  // 定义并初始化
    Print(arr1);
    std::array<int, SIZE> arr2 = {1,2,3,4,5}; // 定义并初始化
    Print(arr2);

    std::array<int, SIZE> arr3{arr};
    Print(arr3);
    std::array<int, SIZE> arr4 = {arr};
    Print(arr4);
    std::array<int, SIZE> arr5 = arr;
    Print(arr5);
    std::array<int, SIZE> arr6;
    arr6 = arr;
    Print(arr6);
    return 0;
}

输出结果:
arr value : 8 0 4199705 0 8
arr value : 0 1 2 3 4
arr value : 2 3 4 5 6
arr value : 1 2 3 4 5
arr value : 0 1 2 3 4
arr value : 0 1 2 3 4
arr value : 0 1 2 3 4
arr value : 0 1 2 3 4

// 元素访问函数
int main()
{
    const int SIZE = 5;
    // 初始化容器
    std::array<int, SIZE> arr;
    for (int i = 0; i < SIZE; ++i) {  // 先定义,后初始化
        arr[i] = i;
    }

    // 元素访问
    // 访问指定的元素,同时进行越界检查
    std::cout << "arr.at(2) : " << arr.at(2) << std::endl;
    // 访问指定的元素,不进行越界检查
    std::cout << "arr[2] : " << arr[2] << std::endl;
    // 访问第一个元素
    std::cout << "arr.front() : " << arr.front() << std::endl;
    // 访问最后一个元素
    std::cout << "arr.back() : " << arr.back() << std::endl;
    // 返回指向内存中数组第一个元素的指针
    printf("arr[0] address : %#p\tarr.data() address : %#p\n", &arr[0], arr.data());
    return 0;
}

输出结果:
arr.at(2) : 2
arr[2] : 2
arr.front() : 0
arr.back() : 4
arr[0] address : 0x65fdf0 arr.data() address : 0x65fdf0

// 使用迭代器对元素访问
int main()
{
    const int SIZE = 5;
    // 初始化容器
    std::array<int, SIZE> arr{1, 2, 3, 4, 5};

    // 迭代器,本身类似指针,stl 提供的一种容器元素操作方法
    // 返回指向起始的迭代器,iterator 迭代器可读写,const_iterator 迭代器可读
    std::array<int, SIZE>::iterator iter = arr.begin();  // 可使用 auto 简化,auto iter = arr.begin();
    for (; iter != arr.end(); ++iter) {
        std::cout << *iter << "\t";
    }
    std::cout << "\n";

    std::array<int, SIZE>::const_iterator iter2 = arr.cbegin();
    for (; iter2 != arr.cend(); ++iter2) {
        std::cout << *iter2 << "\t";
    }
    std::cout << "\n";
    // 返回指向末尾的迭代器,指向最后一个元素的下一个位置
    printf("(arr.data() + 5) addr : %#p\tarr.end() addr : %#p\n", (arr.data() + 5), arr.end());
    printf("(arr.data() + 5) addr : %#p\tarr.cend() addr : %#p\n", (arr.data() + 5), arr.cend());

    // 返回指向起始的逆向迭代器
    std::array<int, SIZE>::reverse_iterator iter3 = arr.rbegin();
    for (; iter3 != arr.rend(); ++iter3) {
        std::cout << *iter3 << "\t";
    }
    std::cout << "\n";
    std::array<int, SIZE>::const_reverse_iterator iter4 = arr.crbegin();
    for (; iter4 != arr.crend(); ++iter4) {
        std::cout << *iter4 << "\t";
    }
    std::cout << "\n";
    // 返回指向末尾的逆向迭代器
    printf("(arr.data() - 1) addr : %#p\tarr.rend() addr : %#p\n", (arr.data() - 1), &(*arr.rend()));
    printf("(arr.data() - 1) addr : %#p\tarr.crend() addr : %#p\n", (arr.data() - 1), &(*arr.crend()));
    return 0;
}

输出结果:
0 1 2 3 4
0 1 2 3 4
(arr.data() + 5) addr : 0x66fdc4 arr.end() addr : 0x66fdc4
(arr.data() + 5) addr : 0x66fdc4 arr.cend() addr : 0x66fdc4
4 3 2 1 0
4 3 2 1 0
(arr.data() - 1) addr : 0x66fdac arr.rend() addr : 0x66fdac
(arr.data() - 1) addr : 0x66fdac arr.crend() addr : 0x66fdac

int main()
{
    const int SIZE = 5;
    // 初始化容器
    std::array<int, SIZE> arr{1, 2, 3, 4, 5};

    // 数组容量访问函数
    // 检查容器是否为空,为空返回 true
    std::cout << std::boolalpha << "arr.empty() : " << arr.empty() << std::endl;
    // 返回容纳的元素数
    std::cout << "arr.size() : " << arr.size() << std::endl;
    // 返回可容纳的最大元素数
    std::cout << "arr.max_size() : " << arr.max_size() << std::endl;
    return 0;
}

输出结果:
arr.empty() : false
arr.size() : 5
arr.max_size() : 5

// 数组操作函数
int main()
{
    const int SIZE = 5;
    auto Print = [](const std::string &str, const std::array<int, SIZE> &arr){
        std::cout << str << " value : \t";
        for (const auto &val : arr) {
            std::cout << val << "\t";
        }
        std::cout << "\n";
    };
    // 初始化容器
    std::array<int, SIZE> arr{1, 2, 3, 4, 5};
    Print("original arr", arr);
    // 数组操作
    // 以指定值填充容器
    arr.fill(10);
    Print("fill arr", arr);

    // 交换数组内容,数组元素个数和类型相同
    std::array<int, SIZE> arr2{};  // 初始化为零
    Print("original arr2", arr2);
    arr2.swap(arr);
    Print("swap arr", arr);
    Print("swap arr2", arr2);
    return 0;
}

输出结果:
original arr value : 1 2 3 4 5
fill arr value : 10 10 10 10 10
original arr2 value : 0 0 0 0 0
swap arr value : 0 0 0 0 0
swap arr2 value : 10 10 10 10 10

#include <iostream>
#include <array>
#include <type_traits>
#include <tuple>

int main()
{
    const int SIZE = 5;
    auto Print = [](const std::string &str, const std::array<int, SIZE> &arr){
        std::cout << str << " value : \t";
        for (const auto &val : arr) {
            std::cout << val << "\t";
        }
        std::cout << "\n";
    };
    // 初始化容器
    std::array<int, SIZE> arr1{1, 2, 3, 4, 5};
    std::array<int, SIZE> arr2{1, 2, 3, 4, 6};

    // 非成员函数 (operator 相关操作在 c++20 中被移除)
    // 按照字典顺序比较 array 中的值
    // operator==、operator!=、operator<、operator<=、operator>、operator>=
    std::cout << std::boolalpha << "arr1 == arr2 : " << (arr1 == arr2) << std::endl;
    std::cout << std::boolalpha << "arr1 != arr2 : " << (arr1 != arr2) << std::endl;
    std::cout << std::boolalpha << "arr1 < arr2 : " << (arr1 < arr2) << std::endl;
    std::cout << std::boolalpha << "arr1 <= arr2 : " << (arr1 <= arr2) << std::endl;
    std::cout << std::boolalpha << "arr1 > arr2 : " << (arr1 > arr2) << std::endl;
    std::cout << std::boolalpha << "arr1 >= arr2 : " << (arr1 >= arr2) << std::endl;

    // 访问 array 的一个元素
    std::cout << "arr1[0] : " << std::get<0>(arr1) << std::endl;
    // 特化 std::swap 算法
    Print("original arr1", arr1);
    Print("original arr2", arr2);
    std::swap(arr1, arr2);
    Print("swap arr1", arr1);
    Print("swap arr2", arr2);

    // 辅助类操作
    // 获得 array 的大小
    std::cout << "std::array<int, SIZE> size : " << std::tuple_size<std::array<int, SIZE> >::value << std::endl;
    // 获得 array 元素的类型
    using type_t = std::tuple_element<0, decltype (arr1)>::type;
    std::cout << std::boolalpha << std::is_same<int, type_t>::value << std::endl;
    return 0;
}

输出结果:
arr1 == arr2 : false
arr1 != arr2 : true
arr1 < arr2 : true
arr1 <= arr2 : true
arr1 > arr2 : false
arr1 >= arr2 : false
arr1[0] : 1
original arr1 value : 1 2 3 4 5
original arr2 value : 1 2 3 4 6
swap arr1 value : 1 2 3 4 6
swap arr2 value : 1 2 3 4 5
std::array<int, SIZE> size : 5
true