数组和C++ std::array详解

1. 数组和std::arraystd::array是c++容器库提供的一个固定大小数组的容器。其与内置的数组相比,是一种更安全、更容易使用的数组类型。std::array在头文件中定义,其声明如下:
template struct array; //c++11 起std::array是一个聚合类型,其语义等同于保有一个c语言风格数组t[n]作为其唯一非静态数据成员的结构体,但其不同于c数组的是它不会自动退化为t*。同时该结构体结合了c风格数组的性能、可访问性和容器的优点(可获取大小、支持赋值和随机访问等)。
2. array的用法2.1 成员函数2.1.1 隐式定义的成员函数
聚合初始化就是从初始化器列表来初始化聚合体,其也是列表初始化的一种方式。
std::array a = {1,2,3};std::array b;b = a; //将a中的每个元素重写到b中,使用operator=时候需要确保a b两个容器长度相等,否则编译失败2.1.2 元素访问atat用于访问指定的元素, 同时进行越界检查 ,该函数返回位于指定位置pos的元素的引用,如果pos不在容器的范围内,则抛出std::out_of_range异常。其函数声明如下:
reference at( size_type pos ); //c++17 前constexpr reference at( size_type pos ); //c++17 起const_reference at( size_type pos ) const; //c++14 前constexpr const_reference at( size_type pos ) const; //c++14 起其具体用法如下:
std::array data = { 1, 2, 3};std::coutreference operator[]( size_type pos ); //c++17 前constexpr reference operator[]( size_type pos ); //c++17 起const_reference operator[]( size_type pos ) const; //c++14 前constexpr const_reference operator[]( size_type pos ) const; //c++14 起注 :通过operator[]符访问不存在的元素是未定义行为。
frontfront用于访问容器的第一个元素,其返回值为容器首元素的引用,其函数原型如下:
reference front(); //c++17 前constexpr reference front(); //c++17 起const_reference front() const; //c++14 前constexpr const_reference front() const; //c++14 起注 :在空容器上对 front 的调用是未定义的。
backback主要功能是用来访问容器最后一个元素,其返回值为容器最后一个元素的引用,其函数原型如下所示:
reference back(); //c++17 前constexpr reference back(); //c++17 起const_reference back() const; //c++14 前constexpr const_reference back() const; //c++14 起注 :在空容器上调用 back 导致未定义行为。
datadata可以直接访问容器底层数组,其返回值为指向作为元素存储工作的底层数组的指针。其函数声明如下:
t* data() noexcept; //c++11 起, c++17 前constexpr t* data() noexcept; //c++17 起const t* data() const noexcept; //c++11 起, c++17 前constexpr const t* data() const noexcept; //c++17 起其返回的指针使得范围[ data(), data() + size() )始终是合法范围。
2.2.3 迭代器begin、end和cbegin、cendbegin和cbegin返回指向deque首元素的迭代器,end和cend返回指向deque末元素后一元素的迭代器。其函数声明如下:
iterator begin() noexcept; //c++17 前constexpr iterator begin() noexcept; //c++17 起const_iterator begin() const noexcept; //c++17 前constexpr const_iterator begin() const noexcept; //c++17 起const_iterator cbegin() const noexcept; //c++17 前constexpr const_iterator cbegin() const noexcept; //c++17 起iterator end() noexcept; //c++17 前constexpr iterator end() noexcept; //c++17 起const_iterator end() const noexcept; //c++17 前constexpr const_iterator end() const noexcept; //c++17 起const_iterator cend() const noexcept; //c++17 前constexpr const_iterator cend() const noexcept; //c++17 起如果array为空,则返回的迭代器将等于end或cend。end和cend指向deque末元素后一元素的迭代器,该元素的表现为占位符,试图访问它将导致未定义行为。
rbegin、rend和crbegin、crendrbegin和crbegin返回指向array首元素的逆向迭代器。它对应非逆向array的末元素,若array为空,则返回的迭代器等于rend或crend。rend和crend返回指向逆向deque末元素后一元素的逆向迭代器,它对应非逆向array首元素的前一元素,此元素表现为占位符,试图访问它导致未定义行为。它们的声明如下:
reverse_iterator rbegin() noexcept; //c++17 前constexpr reverse_iterator rbegin() noexcept; //c++17 起const_reverse_iterator rbegin() const noexcept; //c++17 前constexpr const_reverse_iterator rbegin() const noexcept; //c++17 起const_reverse_iterator crbegin() const noexcept; //c++17 前constexpr const_reverse_iterator crbegin() const noexcept; //c++17 起reverse_iterator rend(); //c++11 前reverse_iterator rend() noexcept; //c++11 起const_reverse_iterator rend() const; //c++11 前const_reverse_iterator rend() const noexcept; //c++11 起const_reverse_iterator crend() const noexcept; //c++11 起
2.2.4 容量emptyempty用来检查容器是否为空,若为空则返回true,否则为false。其函数声明如下:
constexpr bool empty() const noexcept; //c++11 起,c++20 前[[nodiscard]] constexpr bool empty() const noexcept; //c++20 起其底层实现就是检查容器是否无元素,即判断是否begin() == end()。
sizesize函数返回容器中元素数量,即std::distance(begin(), end())。其函数声明如下:
constexpr size_type size() const noexcept; //c++11 起max_sizemax_size函数返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end())。其函数声明为:
constexpr size_type max_size() const noexcept; //c++11 起注 :因为每个 std::array 都是固定大小容器,故 max_size 返回的值等于 n (亦为size所返回的值)
2.2.5 修改器fillfill函数原型如下所示:
void fill( const t& value ); //c++11 起, c++20 前constexpr void fill( const t& value ); //c++20 起fill函数主要用于以指定值填充容器,即将定值 value 赋给容器中的所有元素。
具体用法示例如下:
std::array arr = {1, 2, 3};arr.fill(1); // arr = {1, 1, 1}swapswap函数的主要作用是交换两个array容器的内容,其与deque的swap不同的是不导致迭代器和引用关联到别的容器。其函数声明如下:
void swap( array& other ) noexcept(); //c++11 起, c++20 前constexpr void swap( array& other ) noexcept(); //c++20 起其用法示例如下图所示:
std::array a1{1, 2, 3}, a2{4, 5, 6};auto it1 = a1.begin(); //*it1 = 1auto it2 = a2.begin(); //*it2 = 4int &ref1 = a1[1]; // ref1 = 2int &ref2 = a2[1]; // ref1 = 5std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';// 打印结果为1 4 2 5a1.swap(a2);// 此时a1 = {4, 5, 6},a2 = {1, 2, 3}std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';// 打印结果为4 1 5 2/*注: 交换后迭代器与引用保持与原 array 关联, 例如it1仍指向元素 a1[0] ,ref1仍指代 a1[1] */2.2 非成员函数operator==,!=,=,(std::array)c++提供operator==,!=,=,(std::array)非成员函数用来比较两个array的大小,相关函数及函数声明如下:
//1. ==//返回值:在 array 内容相等时返回 true,否则返回 falsetemplatebool operator==( const std::array& lhs, const std::array& rhs ); //c++20 前templateconstexpr bool operator==( const std::array& lhs, const std::array& rhs ); //c++20 起//2. !=//返回值:在 array 内容不相等时返回 true,否则返回 falsetemplatebool operator!=( const std::array& lhs, const std::array& rhs ); //c++20 前//3. < //返回值:在 lhs 的内容按字典序小于 rhs 的内容时返回 true,否则返回 falsetemplatebool operator< ( const std::array& lhs, const std::array& rhs ); //c++20 前//4. <=//返回值:在 lhs 的内容按字典序小于或等于 rhs 的内容时返回 true,否则返回 falsetemplatebool operator//返回值:在 lhs 的内容按字典序大于 rhs 的内容时返回 true,否则返回 falsetemplatebool operator >( const std::array& lhs, const std::array& rhs ); //c++20 前//6. >=//返回值:在 lhs 的内容按字典序大于或等于 rhs 的内容时返回 true,否则返回 falsetemplatebool operator >=( const std::array& lhs, const std::array& rhs ); //c++20 前//7. //返回值:lhs 与 rhs 中的首对不等价元素的相对顺序,如果有这种元素;否则是 lhs.size() rhs.size()。templateconstexpr operator( const std::array& lhs, const std::array& rhs ); //c++20 起1,2中会检查lhs和rhs的内容是相等,即他们是否拥有相同数量的元素且lhs中每个元素与rhs的相同位置元素比较相等。同时函数中t 必须符合 可相等比较(equalitycomparable) 的要求
3-6中按照字典比较lhs和rhs的内容,其内部等价于调用std::lexicographical_compare函数进行比较。同时函数中t 必须符合[ 可小于比较(lessthancomparable) 的要求。
7中也是按字典序比较lhs和rhs的内容。其内部等价于调用std::lexicographical_compare_three_way进行比较。返回类型同合成三路比较的结果类型。其逻辑大致如下:
lhs < rhs ? std::weak_ordering::less :rhs < lhs ? std::weak_ordering::greater : std::weak_ordering::equivalent//注:通常情况下less对应的是-1,greater对应1,equivalent对应0lhs与rhs中的首对不等价元素的相对顺序,如果有这种元素;否则是lhs.size() rhs.size()。
其具体的应用示例如下所示:
std::array alice{1, 2, 3};std::array bob{7, 8, 9};std::array eve{1, 2, 3};std::cout < < std::boolalpha;// 比较不相等的容器std::cout < < alice == bob returns < < (alice == bob) < < 'n';std::cout < < alice != bob returns < < (alice != bob) < < 'n';std::cout < < alice < bob returns < < (alice < bob) < < 'n';std::cout < < alice <= bob returns < < (alice <= bob) < < 'n';std::cout < bob returns < bob) < < 'n';std::cout < = bob returns < = bob) < < 'n';std::cout < < 'n';// 比较相等的容器std::cout < < alice == eve returns < < (alice == eve) < < 'n';std::cout < < alice != eve returns < < (alice != eve) < < 'n';std::cout < < alice < eve returns < < (alice < eve) < < 'n';std::cout < < alice <= eve returns < < (alice <= eve) < < 'n';std::cout < eve returns < eve) < < 'n';std::cout < = eve returns < = eve) < < 'n';输出结果为
alice == bob returns falsealice != bob returns truealice < bob returns truealice bob returns falsealice >= bob returns false alice == eve returns truealice != eve returns falsealice < eve returns falsealice eve returns falsealice >= eve returns truestd::get(std::array)std::get(std::array)可以用来访问array的一个元素,其函数声明如下:
templatet& get( std::array& a ) noexcept; //c++11 起, c++14 前templateconstexpr t& get( std::array& a ) noexcept; //c++14 起templatet&& get( std::array&& a ) noexcept; //c++11 起, c++14 前templateconstexpr t&& get( std::array&& a ) noexcept; //c++14 起 templateconst t& get( const std::array& a ) noexcept; //c++11 起, c++14 前templateconstexpr const t& get( const std::array& a ) noexcept; //c++14 起templateconst t&& get( const std::array&& a ) noexcept; //c++11 起, c++14 前templateconstexpr const t&& get( const std::array&& a ) noexcept; //c++14 起其主要作用是从a中提取第i个元素.i必须是范围 [0, n) 中的整数值。与at()或 operator[]相反,这在编译时强制。该函数的返回值为a中第i元素的引用。
其具体的用法如下:
std::array arr;// 设置值:std::get(arr) = 1;std::get(arr) = 2;std::get(arr) = 3;// 获取值:std::cout < < ( < < std::get(arr) < < , < < std::get(arr) < < , < < std::get(arr) < < )n;//输出结果为 (1, 2, 3)std::swap(std::array)std::swap(std::array)函数是为std::array特化std::swap 算法。其函数声明如下:
templatevoid swap( std::array& lhs, std::array& rhs ); //c++11 起, c++17 前templatevoid swap( std::array& lhs, std::array& rhs ) noexcept(); //c++17 起, c++20 前templateconstexpr void swap( std::array& lhs, std::array& rhs ) noexcept(); //c++20 起交换 lhs 与 rhs 的内容。调用lhs.swap(rhs)。其具体用法如下:
std::array a1{1, 2, 3}, a2{4, 5, 6};auto it1 = a1.begin(); //*it1 = 1auto it2 = a2.begin(); //*it2 = 4int &ref1 = a1[1]; // ref1 = 2int &ref2 = a2[1]; // ref1 = 5std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';// 打印结果为1 4 2 5std::swap(a1, a2);// 此时a1 = {4, 5, 6},a2 = {1, 2, 3}std::cout < < *it1 < < ' ' < < *it2 < < ' ' < < ref1 < < ' ' < < ref2 < < 'n';// 打印结果为4 1 5 2std::to_arraystd::to_array函数声明如下:
templateconstexpr std::array to_array(t (&a)[n]); //c++20 起templateconstexpr std::array to_array(t (&&a)[n]); //c++20 起std::to_array函数可以从一维内建数组 a 创建 std::array 对象,从 a 的对应元素复制初始化 std::array 的元素。不支持复制或移动多维内建数组。其具体用法如下:
#include #include int main(){ // 复制字符串字面量 auto a1 = std::to_array(foo); static_assert(a1.size() == 4); // 推导元素类型和长度 auto a2 = std::to_array({0, 2, 1, 3}); // 推导长度而元素类型指定 // 发生隐式转换 auto a3 = std::to_array({0, 1, 3}); auto a4 = std::to_array< std::pair>( {{3, .0f}, {4, .1f}, {4, .1e23f}}); // 创建不可复制的 std::array auto a5 = std::to_array({std::make_unique(3)}); // 错误:不支持复制多维数组 // char s[2][6] = { nice, thing }; // auto a6 = std::to_array(s);}std::tuple_sizestd::tuple_size(std::array)函数的声明如下:
templatestruct tuple_size : std::integral_constant //c++11 起{ };其提供作为编译时常量表达式访问std::array中元素数量的方法。用法示例如下:
#include #include templatevoid test(t t){ int a[std::tuple_size::value]; // 能用于编译时 std::cout < < std::tuple_size::value < < 'n';} int main(){ std::array arr; test(arr); //输出 3}std::tuple_elementstd::tuple_element函数主要用来获得 array 元素的类型,其声明如下:
templatestruct tuple_element; //c++11 起其使用类 tuple 接口,提供 array 元素类型的编译时带下标访问。具体使用方法如下:
// 定义 array 并获取位于位置 0 的元素类型std::array data {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};using t = std::tuple_element::type; // int3. 总结数组std::array的优劣:
优点
无开销随机访问。快速遍历;适合线性搜索。劣势
如果元素类型具有较高的复制/分配成本,则可能会变慢(重新排序元素需要复制/移动它们)。在使用array容器的时候,其size必须是常量表达式(即编译时已知)。不支持大小更改操作(调整大小、插入、擦除等)。

导致变频器运行不良的原因,诊断变频器运行不良的方法
GP系列机器人、控制柜YRC1000和YRC1000micro
Intel额外增资10亿 用于使用更先进的工艺技术生产芯片
振动场合的电源模块该如何选型?
聚焦科创输出与人工智能教育| 第十一届中小学STEAM教育大会圆满落幕
数组和C++ std::array详解
开关电源中特殊元件的类型和用途
基于FPGA硬件加速的BittWare StreamSleuth对抗100Gbps
联合电子2022年度销售额突破300亿元
机器视觉在线检测国家标准启动会召开
MAX15054 最新的高边FET驱动器,简化了降压和升降压
HTCOneX9评测 精湛的做工和几乎无缺陷的配置
经科投影幕保养小常识
黑芝麻智能联合BlackBerry QNX打造高性能自动驾驶平台
一文浅谈FlexCAN OTA
国家电网陕北—湖北±800千伏特高压直流工程开工动员大会召开
不同设备如何统一语言编程平台高效开发?本文为你揭秘
新能源汽车都去了哪里(消费群体)_新能源汽车进入普通家庭还需努力
新晋企业六氟磷酸锂扩建项目投产率不足15%
小米Max2什么时候上市最新消息:6.44寸+松果S+6G内存+6000电池的小米Max2马上就来!