概况-摘自百度百科
STL是Standard Template Library的简称,中文名标准模板库,惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用安装额外的库文件。
在C++标准中,STL被组织为下面的17个头文件:<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<numeric>、<queue>、<set>、<unordered_set>、<stack>和<utility>。
It provides four components called algorithms, containers, functions, and iterators.(来源:wiki)
说明:本文代码删去了检验的语句,效果就是注释内容
容器-Vector
[1] Vector创建时候每个元素的默认值
vector<int> a2(10); //默认为0
vector<char> a4(10);//默认为'\0'
vector<bool> a5(10);//默认为'false'
//如果在主函数前面有:
class Test1
{
public:
Test1()
{
cout<<"Copy Constructor Is Called."<<endl;
}
};
//那么
vector<Test1> a6(10);//每一项创建调用拷贝构造函数
vector<int> a7(10,-1);//默认为'-1'
vector<int> a8(a7);
vector<int> a8=a7; //复制a7到a8上
int a11[4]={3,6,9,12};
int *p1=a11;
int *p2=a11+4;
vector<int> a10(p1,p2); //从数组a11[]复制vector上
[2] 对iterator的使用:看做是一个虚拟指针
vector<int>::iterator p3=a10.begin();
vector<int>::iterator p4=a10.end(); // 记住vector<int>::iterator p3= 的句型
cout<<*p3<<endl;
*p3=100; //更改指针所指向对象的数值
for(;p3!=p4;p3++)
{
cout<<*p3<<" ";
} //枚举a10中的所有元素
//vector<int> a2()括号中既可以是地址,也可以来自另一个vector
int a1[]={1,2,3,4,5,6,7,8};
vector<int> a2(a1+2,a1+7); //[1]可以直接用数组地址来喂给vector
for(vector<int>::iterator p=a2.begin();p!=a2.end();p++)
{
cout<<*p<<" ";
} //用iterator来遍历
vector<int> a3(a1,a1+8);
vector<int> a4(a3.begin()+2,a3.end()+7); //[2]也可以来自另一个vector
[3] Vector.xx( ) [empty(), size(), assign(), at()] 以及iterator
//a4.empty()表示a4为空
if(a4.empty())
{
}
//a4.size()用法
cout<<a4.size()<<endl;
//vector的比较:>,<,!=均可以使用。字典序的比较,长一点的那个大
int b1[]={8};
int b2[]={1,2,3,8,0,0,4,2};
vector<int> a5(b1,b1+1);
vector<int> a6(b2,b2+8);//这样子的话 a5>a6
//赋值
a5=a6;
a5.assign(10,100);//10个100
a5.assign(a6.begin()+2,a6.begin()+5);
a5.swap(a4);
//访问每一个元素
cout<<a5[0]<<endl;
cout<<a5.at(0)<<endl;
cout<<a5.front()<<endl;
cout<<a5.back()<<endl;
//反向迭代子 +号表示从后向前走!
vector<int>::reverse_iterator p1=a5.rbegin();
vector<int>::reverse_iterator p2=a5.rend();
for(;p1!=p2;p1++)
{
cout<<*p1<<" ";
}
[3] Vector的反向迭代子与常量迭代子
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int a[]={1,2,3,4,5,6};
vector<int> a1(a,a+6);
vector<int>::reverse_iterator p1=a1.rbegin();
vector<int>::reverse_iterator p2=p1+2;
//将逆向迭代子变成正向迭代子
vector<int>::iterator p3=p2.base()-1; //Change
cout<<*p3<<endl;
*p3=100;
vector<int>::iterator p4=p3+1;
*p4=999;
for(int i=0;i<a1.size();i++)
{
cout<<a1[i]<<" ";
}
cout<<endl;
//常量迭代子: 只能读取,不能改变
vector<int>::const_iterator p5=p3;
cout<<*p5<<endl;//【不能】:*p5=200;
//必需定义成常量迭代子的情况: vector自己本身就是常量
const vector<int> a2={1,2,3,4,5,6};//这样子a2.begin()一定就是常量迭代子
//【不能】:vector<int>::iterator p7=a2.begin();
vector<int>::const_iterator p7=a2.begin();//一定要const
cout<<*p7<<endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//C++ 11的内容
vector<int> a1={1,2,3,4,5,6};
vector<int>::const_iterator p1=a1.cbegin();
vector<int>::const_iterator p2=a1.cend();
vector<int>::const_reverse_iterator p3=a1.crbegin();
vector<int>::const_reverse_iterator p4=a1.crend();
for(;p1!=p2;p1++)
{
cout<<*p1<<" ";
}
cout<<endl;
for(;p3!=p4;p3++)
{
cout<<*p3<<" ";
}
return 0;
}
[4] Vector.xx( ) 元素的增减[前面、后面和中间] [push_back(), pop_back(), 和 insert()]
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//代码不含检验功能
//vector的最后插入元素 a.push_back(); a.pop_back();
vector<int> a1;
a1.push_back(1);
a1.push_back(10);
a1.push_back(100);
a1.push_back(1000);
a1.push_back(10000);
a1.pop_back();
//在Vector中间的位置插入元素(iterator p1 的位置)
int aa[]={1,2,3,4,5,6};
a1.assign(aa,aa+6);
vector<int>::iterator p1=a1.begin()+3;
a1.insert(p1,100);//4之前插入一个100
p1=a1.begin()+2;
a1.insert(p1,6,1);//p1之前插入6个1
a1.assign({1,2,3,4,5,6});
vector<int> a2={10,20,30,40,50};
p1=a1.begin()+2;
vector<int>::iterator p2=a2.begin()+1;
vector<int>::iterator p3=p2+3;
a1.insert(p1,p2,p3);//将p2至p3插入至p1的位置
a1.assign({1,2,3,4,5,6});
a1.insert(p1,{9,8,7}); //C++ 11特有的 直接插
return 0;
}
[5] 实际运用,数组的拼接
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//vector拼接
vector<int> a1={1,2,3,4,5,6};
vector<int> a2={7,8,9,10};
vector<int> a3;
a3=a1;
a3.insert(a3.end(),a2.begin(),a2.end());
for(int i=0;i<a3.size();i++)
{
cout<<a3[i]<<" ";
}
cout<<endl;
//数组拼接
int a[]={1,2,3,4,5,6};
int b[]={7,8,9,10};
vector<int>a4;
a4.assign(a,a+6);
a4.insert(a4.end(),b,b+4);
for(int i=0;i<a4.size();i++)
{
cout<<a4[i]<<" ";
}
cout<<endl;
//同一个数组里面的拼接(移位)
vector<int> a5={1,2,3,4,5,6,7,8};
vector<int> a6(a5.begin(),a5.begin()+5);
vector<int> a7(a5.begin()+5,a5.end());
a7.insert(a7.end(),a6.begin(),a6.end());
for(int i=0;i<a7.size();i++)
{
cout<<a7[i]<<" ";
}
cout<<endl;
return 0;
}
[6] Vector.xx( ) 元素的删除[1个或1串] [erase(p1), erase(p1,p2)]
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//指定位置的元素删除(1个)
vector<int> a1={1,2,3,4,5,6,7,8,9};
vector<int>::iterator p1=a1.begin()+2;
a1.erase(p1);
//指定位置的元素删除(1串)
vector<int> a2={1,2,3,4,5,6,7,8,9};
vector<int>::iterator p2=a2.begin()+2;
vector<int>::iterator p3=a2.begin()+7;
a2.erase(p2,p3);
return 0;
}
[7] Vector.xx( ) 修改数组长度[边长、变短或者变没] [resize(6), clear()]
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//修改vector的长度, 变短后面去掉, 边长后面添0
vector<int> a1={1,2,3,4,5,6,7,8};
a1.resize(6);//{1,2,3,4,5,6}
a1.assign({1,2,3,4,5,6,7,8});
a1.resize(10);//{1,2,3,4,5,6,7,8,0,0}
a1.assign({1,2,3,4,5,6,7,8});
a1.resize(10,100);//{1,2,3,4,5,6,7,8,100,100}
//注意与assign区分
//使vector销毁,变成空
a1.clear();
cout<<a1.size();
return 0;
}
[8] Vector.xx( ) 在类的元素中使用emplce()使用insert()更加高效[emplace(6)]
#include<iostream>
#include<vector>
using namespace std;
class MyValue
{
public:
MyValue(int v)
{
val=v;
}
void ShowInfo() const
{
cout<<"val="<<val<<endl;
}
private:
int val;
};
int main()
{
//emplace 植入
//insert 插入
vector<MyValue> a1;
MyValue b1(10);
MyValue b2(11);
MyValue b3(12);
MyValue b4(13);
MyValue b5(14);
a1.push_back(b1);
a1.push_back(b2);
a1.push_back(b3);
a1.push_back(b4);
a1.push_back(b5);
vector<MyValue>::iterator p1=a1.begin()+1;
/*MyValue c1(100);
a1.insert(p1,c1);*/
a1.emplace(p1,100);//emplace使用方法更加直接、效用更加高
a1.emplace_back(90);
for(int i=0;i<a1.size();i++)
{
a1[i].ShowInfo();
}
return 0;
}
[9] Vector.xx( ) 特例化的模板类: bool类型:反向[flip()]
#include<iostream>
#include<vector>
using namespace std;
int main()
{
//特例化的模板类: bool类型vector 翻转
vector<bool> a1(10,true);
a1.flip();
a1[0].flip();
for(int i=0;i<10;i++)
{
cout<<a1[i]<<" ";
}
cout<<endl;
return 0;
}
[10] iterator = find(,,4) iterator = remove(,,4) 删除所有的某个元素
#include<iostream>
#include<vector>
#include<algorithm>//【注意】这里需要导入algorithm函数
using namespace std;
int main()
{
//查找某Vector中的第一个元素,定位到一个iterator
//若找不到,iterator定位到vector的末尾
vector<int> a1={1,2,3,4,1,2,3,4,1,2,3,4};
vector<int>::iterator p1=find(a1.begin(),a1.end(),4);
//a1.erase(p1);
//p1=find(a1.begin(),a1.end(),5);
//删除所有的某个元素[1](使用iterator = find(,,4))[效率不高]
while(p1!=a1.end())
{
a1.erase(p1);
p1=find(a1.begin(),a1.end(),4);
}
//删除所有的某个元素[2]
vector<int> a3={1,3,3,2,3,4,3};
p1=remove(a3.begin(),a3.end(),3);//【注意】删掉之后后面剩下来的元素的位置不动 例如:{1,2,4,2,3,4,3}
a3.erase(p1,a3.end());//这样子是完全移除
//以上代码可以合并[3]
vector<int> a4={1,3,3,2,3,4,3};
a4.erase(remove(a4.begin(),a4.end(),3),a4.end());
for(int i=0;i<a4.size();i++)
{
cout<<a4[i]<<" ";
}
cout<<endl;
return 0;
}
[11] 数组与vector协同运作
#include<iostream>
#include<vector>
#include<cstring> //【注意】strcpy的使用需要头文件
using namespace std;
int main()
{
//scanf,printf与vector协作
vector<int> a1(3);
for(int i=0;i<a1.size();i++)
{
scanf("%d", &a1[i]);
}
for(int i=0;i<a1.size();i++)
{
printf("%d ", a1[i]);
}
printf("\n");
//将字符串拷贝到一个数组里面去
vector<char> a2(100);
strcpy(&a2[0],"hello");
printf("%s\n",&a2[0]);
return 0;
}
[11]Vector.xx( ) 动态内存分配问题[.reserve(), .capacity()]
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int main()
{
//关于内存的动态分配问题
vector<int> a1(10,-1);
a1.push_back(100);
cout<<a1.capacity()<<endl;//内存比实际所需要的大一些
a1.insert(a1.begin(),{1,2,3,4,5,6,7,8,9,10,11,12});
cout<<a1.capacity()<<endl;//插入的时候元素进行了搬家
a1.reserve(100);
cout<<a1.capacity()<<endl;//免得搬家了
return 0;
}
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int main()
{
//关于内存的动态分配问题
vector<int> a1(10,-1);
a1.push_back(100);
cout<<a1.capacity()<<endl;//内存比实际所需要的大一些
a1.shrink_to_fit();//建议使得内存与实际一样
cout<<a1.capacity()<<endl;
return 0;
}
[12]一个比较容易被忽略的错误:迭代子失效的问题
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int main()
{
//迭代子失效的问题
vector<int> a1={1,2,3,4,5,6,7,8};
vector<int>::iterator p1=a1.begin()+1;
vector<int>::iterator p2=a1.begin()+4;
cout<<*p2<<endl;
a1.erase(p1);
cout<<*p2<<endl;//p2的行为未定义
return 0;
}