文章目录

  • C++ | C++ STL array容器
  • C++ array(`STL array`)容器用法详解
  • `array`容器成员函数汇总
  • 实例1
  • C++ STL array随机访问迭代器
  • `array` 支持迭代器的成员函数
  • `begin()/end()` 和 `cbegin()/cend()`
  • 实例2
  • `rbegin()`/`rend()` 和 `crbegin()`/`crend()`
  • 实例3
  • C++ STL `array`容器访问元素的几种方式
  • 访问array容器中单个元素
  • 访问array容器中多个元素
  • C++ array容器:普通数组的“升级版”
  • 实例4
  • 实例5
  • 实例6
  • 实例7
  • 实例8

C++ | C++ STL array容器

C++ array(STL array)容器用法详解

array 容器是 C++ 11 标准中新增的序列容器(std::array),简单地理解,它就是在 C++ 普通数组的基础上,添加了一些成员函数和全局函数。在使用上,它比普通数组更安全,且效率并没有因此变差。

和其它容器不同,array 容器的大小是固定的,无法动态的扩展或收缩,这也就意味着,在使用该容器的过程无法借由增加或移除元素而改变其大小,它只允许访问或者替换存储的元素。标准手册

#include <array>
using namespace std; // 默认使用std命名空间
template < class T, size_t N > class array;

T:包含的元素的类型。别名为成员类型array::value_type

N:数组的大小,以元素数表示(必须为常量)。

std::array<double, 10> values; // 创建具有 10 个 double 类型元素的 array 容器,初始化为0

std::array<double, 10> values = {0.5, 1.0, 1.5, 2.0, 2.5};

C++ | C++ STL array容器(序列)_成员函数

array容器成员函数汇总

成员函数

功能

begin()

返回指向容器中第一个元素随机访问迭代器

end()

返回指向容器最后一个元素之后一个位置随机访问迭代器,通常和 begin() 结合使用。

rbegin()

返回指向最后一个元素的随机访问迭代器。

rend()

返回指向第一个元素之前一个位置的随机访问迭代器。

cbegin()

begin() 功能相同,只不过在其基础上增加了 const 属性,不能用于修改元素。

cend()

end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

crbegin()

rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

crend()

rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

size()

返回容器中当前元素的数量,其值始终等于初始化 array 类的第二个模板参数 N

max_size()

返回容器可容纳元素的最大数量,其值始终等于初始化 array 类的第二个模板参数 N

empty()

判断容器是否为空,和通过 size()==0 的判断条件功能相同,但其效率可能更快

at(n)

返回容器中 n 位置处元素的引用,该函数自动检查 n 是否在有效的范围内,如果不是则抛出 out_of_range 异常。

front()

返回容器中第一个元素的直接引用,该函数不适用于空的 array 容器。

back()

返回容器中最后一个元素的直接应用,该函数同样不适用于空的 array 容器。

data()

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

fill(val)

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

array1.swap(array2)

交换 array1array2 容器中的所有元素,但前提是它们具有相同的长度和类型。

实例1

/*******************************************************************
 *   > File Name: array-begin.cpp
 *   > Create Time: 2021年09月28日 22:33:02
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    std::array<int, 5> myarray = {2, 16, 77, 34, 50};
    
    std::cout << "myarray contains:";
    /*auto使编译器自动判定变量的类型,输出容器中的所有值*/
    for(auto it = myarray.begin(); it != myarray.end(); ++it){
        std::cout << ' ' << *it;
    }

    //使用 get() 重载函数输出指定位置元素
    std::cout << endl << get<3>(myarray) << endl;;

    return 0;
}

编译、运行:

PS D:\study\cplusplus\day11> make
g++ -o array-begin array-begin.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day11> .\array-begin.exe
myarray contains: 2 16 77 34 50

C++ STL array随机访问迭代器

array 支持迭代器的成员函数

begin()

返回指向容器中第一个元素的正向迭代器;如果是 const 类型容器,在该函数返回的是常量正向迭代器。

end()

返回指向容器最后一个元素之后一个位置的正向迭代器;如果是 const 类型容器,在该函数返回的是常量正向迭代器。此函数通常和 begin() 搭配使用。

rbegin()

返回指向最后一个元素的反向迭代器;如果是 const 类型容器,在该函数返回的是常量反向迭代器。

rend()

返回指向第一个元素之前一个位置的反向迭代器。如果是 const 类型容器,在该函数返回的是常量反向迭代器。此函数通常和 rbegin() 搭配使用。

cbegin()

begin() 功能类似,只不过其返回的迭代器类型为常量正向迭代器,不能用于修改元素。

cend()

end() 功能相同,只不过其返回的迭代器类型为常量正向迭代器,不能用于修改元素。

crbegin()

rbegin() 功能相同,只不过其返回的迭代器类型为常量反向迭代器,不能用于修改元素。

crend()

rend() 功能相同,只不过其返回的迭代器类型为常量反向迭代器,不能用于修改元素。

C++ | C++ STL array容器(序列)_成员函数_02

begin()/end()cbegin()/cend()

实例2

/*******************************************************************
 *   > File Name: array-iterator.cpp
 *   > Create Time: 2021年09月28日 23:08:10
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    array<int, 5> values;
    int h = 1;
    #if 0
    auto first = values.begin(); // OK
    auto last = values.end(); // OK
    #else
    auto first = std::begin(values); // OK
    auto last = std::end (values); // OK
    #endif

    /* 初始化容器 */
    while(first != last){
        *first = h;
        ++first; // ++ 指的是迭代器向右移动一位
        h++;
    }

    first = values.begin();
    while(first != last){
        cout << *first << " ";
        ++first; // ++ 指的是迭代器向右移动一位
    }
    cout << endl;

    auto first1 = values.cbegin();
    while(first1 != values.cend()){
        /* 可以使用 const 类型迭代器访问元素 */
        cout << *first1 << " "; //不能用来修改元素
        ++first1; // ++ 指的是迭代器向右移动一位
    }
    cout << endl;

    return 0;
}

编译、运行:

PS D:\study\cplusplus\day11> make
g++ -o array-iterator array-iterator.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day11> .\array-iterator.exe
1 2 3 4 5
1 2 3 4 5

rbegin()/rend()crbegin()/crend()

实例3

/*******************************************************************
 *   > File Name: array-iterator1.cpp
 *   > Create Time: 2021年09月28日 23:25:10
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
	/* 定义一个数组容器values */
    array<int, 5> values = {1, 25, 33, 16, 10};
    auto first = values.rbegin();
    auto last = values.rend(); 

    while(first != last){
        cout << *first << ' ';
        ++first; // ++ 指的是迭代器向左移动一位
    }
    cout << endl;

    return 0;
}

编译、运行:

PS D:\study\cplusplus\day11> make
g++ -o array-iterator1 array-iterator1.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day11> .\array-iterator1.exe
10 16 33 25 1

C++ STL array容器访问元素的几种方式

访问array容器中单个元素

  • 通过容器名[]的方式直接访问和使用容器中的元素。
values[4] = values[3] + 2.O*values[1];
  • 使用 array 容器提供的 at() 成员函数。
values.at (4) = values.at(3) + 2.O*values.at(1);
  • 使用get<n> 模板函数获取容器元素。
array<string, 5> words{ "one","two","three","four","five" };
cout << get<3>(words) << endl; // Output words[3]
  • 通过 data() 成员函数得到指向容器首个元素的指针
array<int, 5> words{1,2,3,4,5};
cout << *( words.data()+1); // Output words[1]

访问array容器中多个元素

  • array 容器提供的 size() 函数能够返回容器中元素的个数(函数返回值为 size_t 类型)。
double total = 0;
/* 逐个提取容器中的元素,并计算它们的和  */
for(size_t i = 0 ; i < values.size() ; ++i){
    total += values[i];
}
  • 通过调用 array 容器的 empty() 成员函数,即可知道容器中有没有元素。
if(values.empty()){
    std::cout << "The container has no elements.\n";
}  else{
    std::cout << "The container has "<< values.size()<<"elements.\n";  
}
  • 对于任何可以使用迭代器的容器,都可以使用基于范围的循环。
double total = 0;
for(auto&& value : values){
 	total += value;   
}

C++ array容器:普通数组的“升级版”

  • array 容器存储的所有元素位于连续且相邻的内存中

实例4

/*******************************************************************
 *   > File Name: array.cpp
 *   > Create Time: 2021年10月 1日 19:57:20
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    array<int, 5>a{1, 2, 3};
    cout << &a[2] << " " << &a[0]+2 << endl;
    return 0;
}

编译、运行:

PS D:\study\cplusplus\day12> make
g++ -o array array.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day12> .\array.exe
0xffffcbe8 0xffffcbe8

可以看到,a 容器中 &a[2]&a[0] + 2 是相等的。因此在实际编程过程中,我们完全有理由去尝试,在原本使用普通数组的位置,改由 array 容器去实现。

array 容器替换普通数组的好处是,array 模板类中已经封装好了大量实用的方法,在提高开发效率的同时,代码的运行效率也会大幅提高。

  • 使用 array 容器去存储 char*const char* 类型的字符串

实例5

/*******************************************************************
 *   > File Name: array2.cpp
 *   > Create Time: 2021年10月 1日 20:11:14
 ******************************************************************/
#include <iostream>
#include <cstring>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    array<char , 50>a{1,2,3};
    strcpy(&a[0], "https://blog.cs.net/");
    printf("%s\n", &a[0]);
    return 0;
}

编译:

PS D:\study\cplusplus\day12> .\array2.exe
https://blog.cs.net/

array 容器的大小必须保证能够容纳复制进来的数据,存储字符串的话,还需要在末尾放置一个’\0'做为字符串的结束符。strcpy() 在拷贝字符串的同时,会自动在最后添加\0

实例6

/*******************************************************************
 *   > File Name: array-data.cpp
 *   > Create Time: 2021年10月 1日 21:43:52
 ******************************************************************/
#include <iostream>
#include <array>
#include <cstring>
using namespace std;

int main(int argc, char* argv[])
{
    array<char , 50>a{1,2,3};
    strcpy(a.data(), "This is a test.");
    printf("%s\n", a.data());
    return 0;
}

运行:

PS D:\study\cplusplus\day12> .\array-data.exe
This is a test.
  • swap()对两个相同数组(类型相同,大小相同)中元素的进行互换

实例7

/*******************************************************************
 *   > File Name: array-swap.cpp
 *   > Create Time: 2021年10月 1日 22:29:59
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    array<char, 50>addr1{"123456"};
    array<char, 50>addr2{"ABCDEF"};
    addr1.swap(addr2);
    printf("addr1 is: %s\n", addr1.data());
    printf("addr2 is: %s\n", addr2.data());

    return 0;
}

运行:

PS D:\study\cplusplus\day12> .\array-swap.exe
addr1 is: ABCDEF
addr2 is: 123456
  • 当两个 array 容器满足大小相同并且保存元素的类型相同时,两个 array 容器可以直接直接做赋值操作,即将一个容器中的元素赋值给另一个容器。

实例8

/*******************************************************************
 *   > File Name: array-to-array.cpp
 *   > Create Time: 2021年10月 1日 22:57:49
 ******************************************************************/
#include <iostream>
#include <array>
using namespace std;

int main(int argc, char* argv[])
{
    array<char, 50>addr1{"123456"};
    array<char, 50>addr2{"ABCDEF"};
    addr1 = addr2;
    printf("%s\n",addr1.data());
    return 0;
}

运行:

PS D:\study\cplusplus\day12> .\array-to-array.exe
ABCDEF

当两个 array 容器满足大小相同并且保存元素的类型相同时,如果其保存的元素也支持比较运算符,就可以用任何比较运算符直接比较两个 array 容器。

两个容器比较大小的原理,和两个字符串比较大小是一样的,即从头开始,逐个取两容器中的元素进行大小比较(根据 ASCII 码表),直到遇到两个不相同的元素,那个元素的值大,则该容器就大。