微信公众号:阿疯笔记
关注可了解更多的ADAS与编程笔记。问题或建议,请公众号留言。
内容目录
笔记阅读模式STL 简介STL主要内容STL作用代码部分本文用到的一些库文件和声明空间deque容器vector容器deque容器List容器forward_list容器
笔记阅读模式
本文笔记包括文字介绍部分以及代码部分。其中,部分介绍性说明将在代码段中以注释形式展现。
读者可以下载本公众号菜单提供的github地址获取整篇文章涉及的代码。
STL 简介
STL,即standard template library,标准模板库或泛型库,其中包含有大量的模板类和模板函数,是 C++ 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。
STL主要内容
STL 是一些容器、算法和其他一些组件的集合。大致包括内容见图。
STL作用
以 C++ 定义数组的操作为例,在 C++ 中如果定义一个数组,可以采用如下方式:
1int a[n];
这种定义数组的方法需要事先确定好数组的长度,即 n 必须为常量,这意味着,如果在实际应用中无法确定数组长度,则一般会将数组长度设为可能的最大值,但这极有可能导致存储空间的浪费。
所以除此之外,还可以采用在堆空间中动态申请内存的方法,此时长度可以是变量:
1int *p = new int[n];
这种定义方式可根据变量 n 动态申请内存,不会出现存储空间浪费的问题。但是,如果程序执行过程中出现空间不足的情况时,则需要加大存储空间,此时需要进行如下操作:
新申请一个较大的内存空间,即执行int * temp = new int[m];
将原内存空间的数据全部复制到新申请的内存空间中,即执行memecpy(temp, p, sizeof(int)*n);
将原来的堆空间释放,即执行delete [] p; p = temp;
而完成相同的操作,如果采用 STL 标准库,则会简单很多,因为大多数操作细节将不需要程序员关心。下面是使用向量模板类 vector 实现以上功能的示例:
1vector <int> a; //定义 a 数组,当前数组长度为 0,但和普通数组不同的是,此数组 a 可以根据存储数据的数量自动变长。
2//向数组 a 中添加 10 个元素
3for (int i = 0; i 10 ; i++)
4 a.push_back(i)
5//还可以手动调整数组 a 的大小
6a.resize(100);
7a[90] = 100;
8//还可以直接删除数组 a 中所有的元素,此时 a 的长度变为 0
9a.clear();
10//重新调整 a 的大小为 20,并存储 20 个 -1 元素。
11a.resize(20, -1)
对比以上两种使用数组的方式不难看出,使用 STL 可以更加方便灵活地处理数据。所以,大家只需要系统地学习 STL,便可以集中精力去实现程序的功能,而无需再纠结某些细节如何用代码实现。
代码部分
本文用到的一些库文件和声明空间
1//tag:头部
2#include
3#include
4#include
5#include
6#include
7#include
8#include
9using namespace std;
deque容器
1 cout<<"****************** STL container ******************"<<endl;
2 //tag:array
3 cout<<"************ array ************"<<endl;
4 //note:创建
5 std::array<int,4> values{}; // ,T 为类型,n为大小
6 //note:遍历
7 //method1:
8 for(int i=0;i//size()获取容器大小 9 {10 values.at(i)=i; //at(i),获取第i个引用(i从0起)11 }12 cout<3>(values)<<endl; //使用 get() 重载函数输出指定位置元素13 if(!values.empty()) //判断是否为空14 {15 //begin(),end()分别返回第一个元素和最后一个元素的下一个位置的迭代器(和指针类似)16 for(auto val=values.begin();val17 {18 cout<" ";19 }20 }2122 cout<<endl;23 array<int,5> values1;24 int h=1;25 auto first1=values1.begin();26 auto last1=values1.end();27 //method2:28 while(first1!=last1)29 {30 *first1=h;31 ++first1;32 h++;33 }3435 first1=values1.begin();36 while(first1!=last1)37 {38 cout<" ";39 ++first1;40 }41 cout<<endl;4243 //反向迭代器44 array<int,5> values2;45 h=1;46 //可以定义类型为auto,编译时会根据右值返回值自动设置位对应迭代器类型。47 auto first2=values2.rbegin(); //rbegin(),返回最后一个元素对应迭代器48 auto last2=values2.rend(); //rend(),返回第一个元素之前一个位置的迭代器49 while(first2!=last2)50 {51 *first2=h; 52 ++first2; //由于rbegin(),rend()返回的是反向迭代器,故++表示向前移动53 h++;54 }5556 first2=values2.rbegin();57 while(first2!=last2)58 {59 cout<" ";60 ++first2;61 }62 cout<<endl;6364 array<string,5> words{"one","two","three","four","five"};65 cout<3>(words)<<endl;6667 array<int,5> words2{1,2,3,4,5};68 cout<1); //data(),返回指向容器首个元素的指针6970 cout<<endl;
vector容器
1 //tag:vector
2
3 cout<<"************ vector ************"<<endl;
4 cout<<endl;
5 //note:创建
6 vector<int> v{1,2,3,4,5,6,7,8,9,10};
7 cout <<"The method 1:"<<endl;
8 for(int i=0;i 9 {
10 cout<" "; 11 } 12 cout<<endl; 13 cout<<"The method 2:"<<endl; 14 vector<int>::iterator i0; 15 for(i0=v.begin();i0!=v.end();i0++) 16 { 17 cout<" "; 18 } 19 cout<<endl; 20 21 std::vector<double> values01; 22 //重置容器容量 23 values01.reserve(20); 24 25 std::vector<int> primes{2,3,5,7,11,13,17,19}; 26 27 vector<double> values00(20,1.0); 28 29 int num=2; 30 double valueZhi=1.0; 31 std::vector<double> valuesNum(num,valueZhi); //(n,value),两者均可为变量 32 33 34 std::vector<char> valueEg1(5,'c'); 35 vector<char> valueEg2(valueEg1); //复制方式赋值 36 int arrayInt[]={1,2,3,4,5}; 37 vector<int> valueEg3(arrayInt,arrayInt+2); //从传统数组中以部分复制的方式赋值 38 vector<int> valueEg4{1,2,3,4,5}; 39 vector<int> valueEg41(begin(valueEg4),begin(valueEg4)+2); //从容器中以部分复制的方式赋值 40 41 vector<char> valueEg5; 42 valueEg5.push_back('s'); //向容器中尾部添加元素 43 valueEg5.push_back('T'); 44 valueEg5.push_back('L'); 45 printf("The number of element:%d\n",valueEg5.size()); 46 for(auto i=valueEg5.begin();i 47 cout<" "; 48 } 49 cout <<endl; 50 51 valueEg5.insert(valueEg5.begin(),'C'); 52 cout<<"The first element is:"<0)<<endl; 53 cout <<endl; 54 vector<int> valuesNew1{1,2,3}; 55 cout<<"valuesNew1'first element's address:"<endl; 56 auto firstNew1=valuesNew1.begin(); 57 auto endNew1=valuesNew1.end(); 58 valuesNew1.reserve(20); 59 cout <<endl; 60 cout<<"valuesNew1'first element's address:"<endl; 61 firstNew1=valuesNew1.begin(); 62 endNew1=valuesNew1.end(); 63 while(firstNew1!=endNew1) 64 { 65 cout< 66 firstNew1++; 67 } 68 69 if(valuesNew1.empty()) 70 { 71 std::cout<<"The container has no elements.\n"; 72 } 73 else 74 std::cout<<"The container has "<" elements.\n"; 75 76 77 double total=0; 78 for(auto&& value:valuesNew1) 79 total+=value; 80 //访问元素总结 81 // data() 首个元素指针 82 // front(),back(),首末元素值 83 // [i],at(i),直接访问 at()更安全 84 //size()实际大小 VS capacity()容量 85 86 cout <<endl; 87 for(auto&& value:valuesNew1) //基于范围的循环,更多使用请自行搜索相关用法 88 cout<" "; 89 90 cout <<endl; 91 // //2.13 92 // push_back() 创建并剪切 VS emplace_back() 直接创建 93 std::vector<int> demo{1,2}; 94 demo.insert(demo.begin()+1,3); //{1,3,2} 95 96 demo.insert(demo.end(),2,5); //{1,3,2,5,5} 尾部添加2个5 97 std::array<int,3> test{7,8,9}; 98 demo.insert(demo.end(),test.begin(),test.end()); //{1,3,2,5,5,7,8,9} 99100 demo.insert(demo.end(),{10,11}); //{1,3,2,5,5,7,8,9,10,11}101102 for(int i=0;i103 {104 cout<" ";105 }106 cout <<endl;
deque容器
1 //tag:deque
2 cout<<"************ deque ************"<<endl;
3 //note:创建
4 deque<int> d;
5 d.push_back(2); //尾部添加
6 d.pop_back(); //删除尾部元素
7
8 d.push_front(2); //首位添加
9 d.pop_front(); //删除首位添加
10
11 d.emplace_back(2); //直接在尾部添加 {2}
12 d.emplace_front(3); //直接在首位添加 {3,2}
13 d.emplace(d.begin()+1,4); //直接在首位下一位添加 {3,4,2}
14
15 for(auto i:d)
16 {
17 cout<" ";18 }1920 d.erase(d.begin()); //删除首个元素 {4,2}21 d.erase(d.begin(),d.end()); //删除首个至最后一个元素 NULL22 cout<<endl;23 for(auto ii:d)24 {25 cout<" ";26 }27 cout<<endl;
List容器
1 //tag:list
2 cout<<"************ list ************"<<endl;
3 //note:创建
4
5 std::list<double> valuesList;
6 valuesList.push_back(3.1);
7 valuesList.push_back(2.2);
8 valuesList.push_back(2.9);
9 cout<<"valuesList size:"<endl;10 valuesList.sort();11 for(auto it=valuesList.begin();it!=valuesList.end();++it)12 {13 std::cout<" ";14 }1516 std::list<int> mylist{1,2,3,4};17 //note:访问18 //list 容器不支持随机访问,未提供下标操作符 [] 和 at() 成员函数,也没有提供 data() 成员函数。19 int &firstML=mylist.front(); //首个元素引用20 int &lastML=mylist.back(); //最后一个元素引用21 cout<" "<endl;22 firstML=10;23 lastML=20;24 cout<" "<endl;25 //note:插入26 //和 insert() 成员方法相比,splice() 成员方法的作用对象是其它 list 容器27 //其功能是将其它 list 容器中的元素添加到当前 list 容器中指定位置处。28 list<int> mylist1{1,2,3,4},mylist2{10,20,30};29 list<int>::iterator itML2= ++mylist1.begin();30 mylist1.splice(itML2,mylist2); //mylist1={1,10,20,30,2,3,4} mylist2={}3132 mylist2.splice(mylist2.begin(),mylist1,itML2); //it 仍指向2!!!!!!!33 //故此时 mylist1={1,10,20,30,3,4}(2没了) ,mylist2={2}3435 mylist2.splice(mylist2.begin(),mylist1,mylist1.begin(),mylist1.end());36 cout <<endl;37 cout<<"mylist1 contains " <" elements"<<endl;38 cout<<"mylist2 contains " <" elements"<<endl;39 cout<<"mylist2:"; //mylist2={1,10,20,30,3,4,2}40 for(auto iter=mylist2.begin();iter!=mylist2.end();++iter)41 {42 cout<" ";43 } 44 cout <<endl;45 cout <<endl;4647 //note:删除48 //method1:49 //remove(val) 删除容器中所有等于 val 的元素。50 //method2:51 //pop_front() 删除位于 list 容器头部的一个元素。52 //pop_back() 删除位于 list 容器尾部的一个元素。53 //method3:54 //clear() 删除所有55 //method4:56 //unique();57 list<double> mylistNewNew{1,1.2,1.2,3,4,4.5,4.6};58 mylistNewNew.unique(); //unique() 删除容器中相邻的重复元素,只保留一份。5960 for(auto it=mylistNewNew.begin();it!=mylistNewNew.end();++it)61 {62 cout<' ';63 }64 cout<<endl;6566 mylistNewNew.unique(demoForListClear);67 for(auto it=mylistNewNew.begin();it!=mylistNewNew.end();++it)68 {69 std::cout<' ';70 }71 cout<<endl;72 std::list<int> mylistNewNew2{ 15, 36, 7, 17, 20, 39, 4, 1 };73 //删除 mylist 容器中能够使 lamba 表达式成立的所有元素。74 //method5:75 //remove_if() 删除容器中满足条件的元素76 mylistNewNew2.remove_if([](int value){return (value<10);}); 77 for (auto it = mylistNewNew2.begin(); it != mylistNewNew2.end(); ++it)78 std::cout <' ' <79 cout<<endl;
其中,
1//二元谓词函数
2bool demoForListClear(double first,double second)3{
4 return (int(first)==int(second));
5}
forward_list容器
1 //tag:forward_list
2 cout<<"************ forward_list ************"<<endl;
3 //note:创建
4 std::forward_list<int> my_wordsFL{1,2,3,4};
5 //forward_list 容器中是不提供 size() 函数的,但如果想要获取 forward_list 容器中存储元素的个数
6 //可以使用头文件 中的 distance() 函数
7 int countFL = std::distance(std::begin(my_wordsFL), std::end(my_wordsFL));
8 cout < 9 //forward_list 容器迭代器的移动除了使用 ++ 运算符单步移动,还能使用 advance() 函数
10 std::forward_list<int> valuesFL{1,2,3,4};
11 auto itFL = valuesFL.begin();
12 advance(itFL, 2);
13 while (itFL!=valuesFL.end())
14 {
15 cout <" ";
16 ++it;
17 }
参考文章及部分图片来源:
C语言中文网:http://c.biancheng.net/stl/stl_basic/
下期内容:STL | 容器(二)之关联式容器