概述:
array是c++11新增的静态数组类型(就是数组的大小定义之后就无法改变),数组我们平时使用的很多,那为什么在c++11增加一个array静态数组的类呢?
获取大小:
array的提出可以完全代替我们平时使用的数组,而且其具有更高的安全性,而且使用array表示数组,我们不需要在使用sizeof计算数组的长度,或者在函数中传递一个数组的长度,直接调用array的size()方法就可以获取到数组大大小。
安全检查:
而且在使用下标操作的时候,array数组会进行下标越界的检查,而传统的数组不会。(应该说还在debug模式下,会进行安全检查。在release模式下,会追求更高的效率,会忽略)#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[_Pos];
这是array标准库中重载的[]函数的函数体,当对应的宏满足条件的时候,或执行一个宏函数,进行越界检查。否则,不进行越界检查,直接返回数组。
使用效率:
相对于原来的数组,效率是差不多的。因为array底层的数据是存储在栈上面的(vector底层是在堆上面存储的),所以其效率是很快的。
当然,c++11的array是一种选择,你可以继续使用原来的数组,这样你需要自己计算长度或者确保安全性,array的安全性高,因为它要进行相应的检测,所以其性能要比普通的数组性能低。(但是并没有低太多) -- 所以,应该使用array,因为它会更加的安全。
首先我们使用函数传参来对比一下array相对于普通数组的优势.
- 普通数组
void func(int *arr, int len) {
}
函数内部无法知道数组的长度,需要使用第二个参数传递到函数中才行。
- std::array
void func(std::array<int ,5> &arr) { // 假设这里定义的是长度为5的静态数组
}
使用array我们只需要传入一个静态数组的对象引用就行,其内部可以调用size()进行获取长度
- 疑问
可能会有以下疑问,在传递array对象的时候,我们需要在<>指明它的大小吗? 那不是一样在函数传递的时候得知道大小。
当然,我们可以在不指定大小的情况下,实现传递array数组。using Array = std::array<int, 5>;
void func(Array &arr) {
}
首先array是一个类模板,和之前的容器使用方式是完全类似的,我们要使用array必须导入头文件#include <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) | 交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型。 |
1. 创建array对象
- array<T,size_t size> 数组名; // T表示数组存储的类型,size表示数组存储的元素个数。
2. 数组的赋值
因为静态数组不向vector那样,可以根据插入的数据自动扩充空间,其空间在定义的时候就已经规定好了,不能根据插入的数据改变空间的大小。
所以对于array对象而言没有添加元素或者删除元素的函数,只存在对数组进行赋值的。
1)使用初始化列表进行赋值
- 对象定义的时候赋值:
std::array<int, 5> a1{1,2,3,4,5};
- 给已经定义的对象赋值:
std::array<int, 5> a2;
a2 = {1,2,3,4,5};
2)使用已存在的数组进行赋值
- 对象定义的时候赋值:
std::array<int, 5> a1{1,2,3,4,5};
std::array<int, 5> a2(a1);
- 给已经定义的对象赋值:
std::array<int, 5> a3;
a3 = a2;注意: 上面互相赋值的两个数组,必须存储的类型和存储数据的个数都是一样的,否则就会出错。
3)使用下标运算符和at()函数进行赋值
- 使用下标运算符:
std::array<int,5> a1;
a1[1] = 10;
a1[2] = 20;注意: 数组使用下标运算符的时候,应该小心越界。
- 使用at()函数:
std::array<int,5> a1;
a1.at(0) = 10;
a1.at(1) = 20;注意: at()函数相对于[]运算符,增加了异常处理机制,但是也应该注意越界。
4)使用fill()函数
- 使用fill()函数: 可以将数组使用某个值进行填充。
std::array<int, 5> a1;
a1.fill(5); // 将数组中的元素都设置为5for (auto i : a1) {
std::cout << i << std::endl; // 打印出5个5
}
3. 数组的访问
1)使用下标运算符和at()进行访问
std::array<int,5> a1{1,2,3,4,5};
- 使用[]进行访问:
std::cout << a1[0] << std::endl;
- 使用at()函数进行访问:
std::cout << a1.at(0) << std::endl;
注意: 使用[]和at()访问的时候都需要注意数组越界。
2)使用front()和back()函数
std::array<int,5> a1{1,2,3,4,5};
- 使用front()和back()访问:
std::cout << a1.front() << std::endl; // front() 返回数组中第一个元素
std::cout << a1.back() << std::endl; // back() 返回数组中最后一个元素
- 通过front()和back()修改数组中第一个和最后一个元素
因为两个函数返回的都是数组中存储元素的引用,素以我们可以通过这两个函数的返回值来修改数组的第一个元素和最后一个元素。
a1.front() = 6; // 将数组中第一个元素修改为6
a1.back() = 10; // 将数组中最后一个修改为10
3)使用data()函数
std::array<int,5> a1{1,2,3,4,5};
- data()函数: 返回调用数组首元素的指针(地址)
auto ptr = a1.data();
std::cout << *ptr << std::endl; // 输出的结果为1,所以ptr为首元素的地址。
4. 数组的长度
1)使用size()
std::array<int,5> a1{1,2,3,4,5};
- size()函数: 返回调用数组的元素个数
std::cout << a1.size() << std::endl; // 输出的结果为5,为数组的元素个数
5. 数组的迭代器
和它的容器一样,我们也可以使用迭代器来遍历数组中的元素。
其它的迭代器使用方式和其它容器介绍的迭代器使用方式一样的,此处就不多介绍了,可以查看其它容器的相关内容。
std::array<int, 5> a1{1,2,3,4,5};
for (auto it = a1.begin(); it != a1.end(); it++) {
std::cout << *it << std::endl; // 输出1,2,3,4,5
}
6. swap()函数
- swap()函数可以对两个数组对象中的元素进行互换。
std::array<int, 5> a1{1,2,3,4,5};
std::array<int, 5> a2{ 10,11,12,13,14};
a1.swap(a2); // 将两数组元素中的数据进行互换注意: 互换的条件,两个数组存储的数据类型和数据个数必须都相同否则就会出错。