最近刷题时一直用的是C++,而 stl(标准模板库) 是C++里面非常重要的程序库,为此我会持续更新stl内的相关内容。里面的内容很多,不可能看几篇博客就能熟练掌握的,还得多用,熟能生巧,过程中会结合写过的一些题来加深对stl的使用。
预热
本小节将介绍vector,在介绍vector前不妨先简单介绍下array吧
array< T , N >:表示可以存储 N 个 T 类型的元素,T可以是任意类型的元素。此类容器一旦建立后,其长度便是固定不变的,不能增加或删除元素,而只能改变某个元素的值;
array和我们经常接触的数组别无二致,都无法增加和删除元素。
但它比数组更好用,和标准的数组相比,array 容器的额外幵销很小,同时提供了两个优点:如果使用 at(),当用一个非法的索引访问数组元素时,能够被检测到,因为容器知道它有多少个元素,这也就意味着数组容器可以作为参数传给函数,而不再需要单独去指定数组元素的个数。
array容器包含在array头文件中,如果你在使用 stl 等C++其他标准库时,忘了头文件名称或者不愿意一个个添加头文件,不妨使用它
#include <bits/stdc++.h>
使用它时,你就不需要一个个写头文件了,当然使用时,注意你使用C++的版本。
array的定义
我们使用三种不同的方式定义array,并打印它们的值,第四种是给定义好了的array所有元素赋初值。array一旦定义了,其大小就是固定的了。
示例如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
array<int,5> my_array1;
for(int i=0;i<my_array1.size();i++){
cout<<my_array1[i]<<" ";
}
cout<<endl;
array<int,5> my_array2 {};
for(int i=0;i<my_array2.size();i++){
cout<<my_array2[i]<<" ";
}
cout<<endl;
array<int,5> my_array3 {1,2,3,4};
for(int i=0;i<my_array3.size();i++){
cout<<my_array3[i]<<" ";
}
cout<<endl;
array<int,5> my_array4 {};
my_array4.fill(2020);
for(int i=0;i<my_array4.size();i++){
cout<<my_array4[i]<<" ";
}
cout<<endl;
return 0;
}
结果:
image.png
my_array1.size() 是得到容器的大小,使用它可以一定程度上防止访问越界。
- array<int,5> my_array1,只是定义了该array容器,没有为其指定初值,因此容器中的内容不是我们所预期的。
- array<int,5> my_array2 {},使用该语句初始化array容器后,容器中所有的元素都是0。
- array<int,5> my_array3 {1,2,3,4},该容器的前四个值被赋值,而第五个由于没有被赋值,默认为0。
- array<int,5> my_array4 {}; my_array4.fill(2020); 该容器内所有的值被统一为2020。
array的访问
与数组相似,array可以在方括号中使用索引访问元素
#include <bits/stdc++.h>
using namespace std;
int main(){
array<int,10> my_array1 {1,1};
my_array1[2]=my_array1[1]+my_array1[0];
cout<<my_array1[2]<<endl;
return 0;
}
这样访问元素,很容易引起越界,例如,我们来求该容器内斐波那契数列的每一项
my_array1[i]=my_array1[i-1]+my_array1[i-2];
如果稍加不注意,就会引起越界的,虽然这个错误很明显,但是实际中类似的错误还是会很难完全避免的。
为了防止访问越界,我们可以使用 at 方法
示例如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
array<int,10> my_array1 {1,1};
for(int i=0;i<my_array1.size();i++){
my_array1[i+2]=my_array1[i+1]+my_array1[i];
}
for(int i=0;i<my_array1.size();i++){
cout<<my_array1[i]<<" ";
}
array<int,10> my_array2 {1,1};
for(int i=0;i<my_array1.size();i++){
my_array2.at(i+2)=my_array2.at(i+1)+my_array2.at(i);
}
for(int i=0;i<my_array2.size();i++){
cout<<my_array2[i]<<" ";
}
return 0;
}
结果如下:
image.png
当然这里,俩种方法都发现了访问越界,实际中的情况会比这更复杂,隐蔽。使用at方法是一个行之有效的方法。
size()可以得到当前容器的元素个数,如果容器中没有元素的话,也可以使用成员函数 empty() 会返回 true。
同时,对于任何可以使用迭代器的容器,都可以使用基于范围的循环
示例如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
array<int,10> my_array {};
my_array.fill(1);
if(my_array.empty()){
cout<<"my_array is NULL";
}else{
cout<<"my_array is not NULL,"<<"size is "<<my_array.size()<<endl;
}
//为my_arraty赋初值
for(int i=2;i<my_array.size();i++){
my_array.at(i)=my_array.at(i-1)+my_array.at(i-2);
}
//访问
for(auto&& _array : my_array){
cout<<_array<<" ";
}
cout<<endl;
return 0;
}
结果如下:
image.png
这里介绍一个模板函数get<n>(),它能够获取到容器的第 n 个元素。需要注意的是,n必须是一个在编译时就可以的常量表达式,也就是它不能是一个循环变量。比如,你想这样写
//访问get<>
//允许
cout<<get<0>(my_array)<<endl;
//不允许,i是一个循环变量
for(int i=0;i<my_array.size();i++){
//不允许
// cout<<get<i>(my_array)<<" ";
//允许
cout<<get<1+1>(my_array)<<" ";
}
结果如下:
image.png
之后将介绍 array 的迭代器以及其他常用成员函数的使用。
网友评论