泛型编程
编写程序时不具体的写定数据类型。提高重用性
1.模板
1.1函数模板(掌握)
编译器会根据传入参数的类型 替换T
注意:系统有swap函数 。下方函数名Swap首字母大写
#include <iostream>
using namespace std;
template <class T>
void Swap(T &a,T &b){
T t=a;
a=b;
b=t;
}
int main()
{
int m=10,n=20;
Swap(m,n);
cout<<m<<" "<<n<<endl;
double m2=1.5,n2=2.5;
Swap(m2,n2);
cout<<m2<<" "<<n2<<endl;
}
add模板函数
#include <iostream>
using namespace std;
template <class T>
T add(T a,T b){
return a+b;
}
int main()
{
int a=2,b=3;
int c=add(a,b);
cout<<c<<endl;
string str1="he";
string str2="llo";
cout<<add(str1,str2);
}
除了让编译器根据传入参数类型替换Ts外,也可以告知使用何种类型,实例化模板
#include <iostream>
using namespace std;
template <class T>
T Inc(T a){
return a+1;
}
int main()
{
cout<<Inc<double>(4)/2<<endl;
}
1.2.类模板(掌握)
如果要创建类的形式和功能类似。可以创建类模板,提高重用性和开发效率
template <typename T> 和template <class T> 都可以
#include <iostream>
using namespace std;
template <typename T>
class Demo
{
private:
T value;
public:
Demo(T value):value(value){}
void set_value(T value){
this->value=value;
}
T get_value(){
return value;
}
};
int main()
{
Demo<int> d(10);
cout<<d.get_value()<<endl;
d.set_value(11);
cout<<d.get_value()<<endl;
Demo<bool> d2(true);//true: 1 false:0
cout<<d2.get_value()<<endl;
}
模板类 类内声明类外定义
#include <iostream>
using namespace std;
template <typename T>
class Demo
{
private:
T value;
public:
Demo(T value);
void set_value(T value);
T get_value();
};
template <typename T>
Demo<T>::Demo(T value):value(value){}
template <typename T>
void Demo<T>::set_value(T value){
this->value=value;
}
template <typename T>
T Demo<T>::get_value(){
return value;
}
int main()
{
Demo<int> d(10);
cout<<d.get_value()<<endl;
d.set_value(11);
cout<<d.get_value()<<endl;
Demo<bool> d2(true);
cout<<d2.get_value()<<endl;
}
2.STL
用模板实现泛型编程,泛型编程中最成功的案例就c++中的标准模板库STL
STL包括的内容:
算法 sort()
容器
迭代器
容器:存放数据的类模板
顺序容器:不是按传入数据大小排序的 而是可以指定传入的位置
关联容器: 传入的数据进行排序 没法指定传入的位置
string字符串(熟悉)
代替 c语言中的char *
#include <iostream>
using namespace std;
int main()
{
string s="hello";
cout<<s[0]<<endl;
//cout<<s.at(6)<<endl; 会有检查
cout<<s.length()<<endl;
cout<<s.size()<<endl;
for(char ch:s){
cout<<ch<<endl;
}
}
string创建
#include <iostream>
using namespace std;
int main()
{
//创建string
string s1="hello";
string s2("world");
string s3(s1);
//参数1:长度
//参数2:每个字符是什么
string s4(5,'*');
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
cout<<s4<<endl;
//string s5='a'; //常字符不能直接初始化
string s5;
s5='s';
}
string拼接
#include <iostream>
using namespace std;
int main()
{
string s1="hello";
s1[0]='H';
cout<<s1<<endl; //Hello
//第一种拼接
string s2="Tom";
s1+=s2;
cout<<s1<<endl; //HelloTom
//第二种拼接 支持链式调用
s1.append(s2).append(s2); //拼接字符串多时这种效率高
cout<<s1<<endl; //HelloTomTomTom
//追加一个字符
s1.push_back('#');
cout<<s1<<endl; //HelloTomTomTom#
}
string字符串关系运算符比较
返回值都是bool类型。成立返回true 否则返回false
#include <iostream>
using namespace std;
int main()
{
//比较的编码
// == ,>, >= ,< ,<= ,!=
string s1("hello"),s2("hello"),s3("hell");
bool b=(s1==s2);
cout<<b<<endl; //1
b=(s1==s3);
cout<<b<<endl; //0
b=(s1>s3);
cout<<b<<endl; //1
}
取子字符串,替换
#include <iostream>
using namespace std;
int main()
{
string s1("hello"),s2("hello"),s3("hell");
swap(s1,s3);
cout<<s1<<" "<<s3<<endl; //hell hello
//参数1:下标开始位置
//参数2:截取的个数
string s4=s2.substr(1,4);//ello
cout<<s4<<endl;
//参数1:替换的开始位置
//参数2:替换字符的数量
//参数3:替换的新内容
s2.replace(1,2,"www"); //只是替换 不会覆盖字符串后面内容
cout<<s2<<endl; //hwwwlo
//截取
s2.erase(5);
cout<<s2<<endl; //hwwwl
s2.erase(2);
cout<<s2<<endl; //hw
}
string插入
#include <iostream>
using namespace std;
int main()
{
string s1("good");
string s2("Tom");
s1.insert(2,s2); //goTomod
string s3("Jerry");
//第1个参数:开始插入的下标
//第2个参数:准备插入的内容
//第3个参数:准备插入的内容的起始下标
//第4个参数:个数
s3.insert(2,s1,0,2); //Jegorry
cout<<s1<<endl;
cout<<s3<<endl;
}
vector向量(掌握)
内部是动态数组
删除和插入效率低,可以高效的存取
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v(5);
for(int i=0;i<5;i++){
v[i]=i;
}
v.push_back(5); //后面追加5
v.push_back(6); //后面再追加6
cout<<v.size()<<endl; //7 大小动态变化
for(int i:v){
cout<<i<<" ";
}
}
end()返回最后一个元素后面的迭代器
begin()返回第一个元素的迭代器
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v(5);
for(int i=0;i<5;i++){
v[i]=i;
}
v.push_back(5); //后面追加5
v.push_back(6); //后面再追加6
cout<<v.size()<<endl; //7
//v.begin()返回第一个位置的迭代器
v.insert(v.begin(),100);
v.insert(v.begin()+2,200);
v.insert(v.end()-1,300); //插入倒数第2位置
v.erase(v.begin()+1); //删除第2个数
v.erase(v.end()-2);//删除倒数2个
for(int i:v){
cout<<i<<" ";
}
}
pop_back() 删除最后一个位置
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> vch;
vch.push_back('a');
vch.push_back('b');
vch.push_back('c');
vch.insert(vch.begin()+2,'f'); //在第3位置插入
vch.pop_back();
vch.erase(vch.end()-2); //af 删除倒数第2个
vch[0]='f'; //ff
vch.at(0)='F'; //Ff
cout<<vch.size()<<endl; //2
for(char ch:vch){
cout<<ch<<" ";
}
}
list 列表(掌握)
内部是双向链表来实现的,可以高效的插入和删除。但是存取效率较低。不支持下标操作。需要迭代指针操作元素
#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
list<string> lis;
cout<<lis.empty()<<endl; //是空 返回1
lis.push_back("AA");
lis.push_back("BB");
lis.push_back("CC");
cout<<lis.empty()<<endl; //非空 返回0
for(string s:lis){
cout<<s<<" ";
}
}
pop_back()
pop_front()
#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
list<string> lis;
cout<<lis.empty()<<endl; //1
lis.push_back("AA");
lis.push_back("BB");
lis.push_back("CC");
//删除最后一个
lis.pop_back();//AA BB
//删除第一个
lis.pop_front();//BB
cout<<lis.empty()<<endl; //0
for(string s:lis){
cout<<s<<" ";
}
}
list不能用 begin()+数字 的形式访问到元素,因为它是链式储存的,不是连续空间。用迭代器方法删除指定位置
list<string>::iterator iter
list<string>是容器类名
iter 是取的迭代器名
list<string> lis;
cout<<lis.empty()<<endl; //是空 返回1
lis.push_back("AA");
lis.push_back("BB");
lis.push_back("CC");
lis.push_back("DD");
lis.push_back("EE");
cout<<lis.empty()<<endl; //非空 返回0
//用迭代器的方式
list<string>::iterator iter=lis.begin();
advance(iter,2);//移动到第三位置
lis.erase(iter);
for(string s:lis){
cout<<s<<" ";
}
deque 队列
兼顾vector和list。性能在两者之间。方法是通用的,可以直接调用
关联容器(掌握)
关联容器内部存放是按一定顺序排列。物理上并不是像数组一样连续的空间。
常见的关联容器map。map是键和值对应存在的
数据是成对出现,前面的叫键,后面叫值。可以通过键访问值
可以使用迭代器遍历,比普通方式效率高
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <map>
using namespace std;
int main()
{
map<string,int> mp1;
cout<<mp1.empty()<<endl; //1
mp1.insert(pair<string,int>("age",18));
mp1.insert(pair<string,int>("height",170));
mp1.insert(pair<string,int>("salary",5000));
//去除键对应的值
cout<<mp1["height"]<<endl;
cout<<mp1["salary"]<<endl;
if(mp1.find("xxx")==mp1.end()) {
cout<<"没有找到"<<endl;
}else{
cout<<"找到"<<endl;
}
if(mp1.find("age")!=mp1.end()){
cout<<"键是存在的"<<endl;
}
//迭代器遍历 for(map<string,int>::iteratorite=mp1.begin();ite!=mp1.end();ite++)
{
cout<<ite->first<<":"<<ite->second<<endl;
}
}
迭代器(掌握)
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <map>
using namespace std;
int main()
{
string s="abcde";
for(string:: iterator its=s.begin(); its!=s.end();its++){
cout<<*its<<" "<<endl;
}
vector<string> v(5,"hello");
for(vector<string>::iterator itv=v.begin(); itv!=v.end();itv++){
cout<<*itv<<endl;
}
}