泛型编程和STL基础学习(C++)(未完待续)

一往情深深几许,深山夕照深秋雨。
 
泛型编程:函数模板和类模板

函数模板: 
template<typename T>		//typename也可使用class 
void func(T &a){
    
    }

两种方式使用模板:
	1、自动类型推导
	func(a)
	2、显式指定类型
	func<int>(a)

模板的目的是为了提高代码的复用性,将类型参数化
注意事项:
	·自动类型推导,必须推导出一致数据类型T,才可以使用
	·模板必须要确定出T的数据类型,才可以使用
 
普通函数和模板的区别:
	自动类型推导	不会发生隐式类型转换
	显式制定类型	会发生隐式类型转换
		 
普通函数和模板函数的调用规则
	·如果函数模板和普通函数都可以实现,优先调用普通函数
	·可以通过空模板参数列表来强制调用函数模板
	·函数模板也可以发生重载
	·如果函数模板可以产生更好的匹配,优先调用函数模板 

模板的局限性:
	模板并不是万能的,有些特定数据类型,需要用具体化方式做特殊实现

	·利用具体化的模板,可以解决自定义类型的通用化
	·学习模板并不是为了写模板,而是在STL能够运用系统提供的模板 
	
类模板:
	·建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表
	template<typename T>template<class NameType, class AgeType>
	class Person
	{
    
    
		public:
			Person(NameType name, AgeType age)
			{
    
    
				this -> m_Name = name;
				this -> m_Age = age;
			}
			NameType m_Name;
			AgeType m_Age;
	}
	
	void test()
	{
    
    
		Person<string, int>p1("suwukong", 999);
	}

类模板与函数模板的区别:
	·类模板没有自动推导的使用方式
	·类模板在模板参数列表中可以有默认参数
	
类模板中成员函数的创建时机:
	一开始并不创建
	在调用的时候才会被创建

类模板对象做函数参数
	类模板实例化出的对象,向函数传参的方式
	一共有三种传入方式:
		1、指定传入的类型  	--直接显示对象的数据类型
		2、参数模板化		--将对象的参数变为模板进行传递
		3、整个类模板化		--将这个对象类型 模板化进行传递

类模板与继承:
	·当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
	·如果不指定,编译器无法给子类分配内存
	·如果想灵活指定出父类中T的类型。子类也需要变为类模板

类模板成员函数类外实现:

类模板分文件编写:
问题:
	类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
	·一、直接包含.cpp 源文件
	·二、将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定名称,并不是强制
	 
***********************************************************
面向对象:封装,继承和多态 
STL
·standard Template Library
·STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator)
·容器和算法之间通过迭代器进行无缝连接
·STL几乎所有的代码都采用了模板类或者模板函数

STL六大组件:
	容器、算法、迭代器、仿函数、适配器、空间配置器

容器:就是讲运用最广泛的一些数据结构实现出来
	·序列式容器
		强调值得排序,序列式容器中的每个元素均有固定的位置
	·关联式容器
		二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(algorithm) 
	·质变算法
		是指运算过程中会更改区间内元素的内容,例如拷贝、替换、删除等等
	非质变算法
		是指运算过程中不会更改区间内元素的内容,例如查找、计数、遍历、寻找极值等等
迭代器:提供一种方法,使之能够依序寻访某个容器所含的各个元素,二又不暴露该容器内部的表示方式


string容器
本质:
	·string是C++风格的字符串,而string本质上是一个类
string和char*的区别:
	·char*是一个指针 
	·string是一个类,类内 不封装了char*,管理这个字符串,是一个char*型的容器。
特点:
	string类内部封装了很多成员方法
	例如:查找find,拷贝copy,删除delete,替换replace, 插入insert
	string 管理char* 所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责

构造函数: 
string();					//创建一个空的字符串,例如:string str;
string(const char* s);		//使用字符串初始化
string(const string& str);	//使用一个string对象初始化里另一个string对象
string(int n, char c);		//使用n个字符c初始化 

string赋值操作:
string & operator=(const char* s);		//char*类型字符串 赋值给当前的字符串 
string & operator=(const string &s);	//把字符串s赋值给当前的字符串	
string & operator=(char c);				//把字符赋值给当前的字符串
string & assign(const char* s);			//把字符串s赋值给当前的字符串
string & assign(const char* s, int n);	//把字符串s的前n个字符赋值给当前的字符串
string & assign(const string &s);		//把字符串s赋值给当前的字符串
string & assign(int n, char c);			//用n个字符c赋值给当前的字符串

string查找和替换:
int find(const string & str, int pos = 0)const;		//查找str第一次出现的位置,从pos开始查找
int find(const char* s, int pos = 0)const;			//查找s第一次出现的位置,从pos开始查找
int find(const char* s, int pos, int n)const;		//从pos查找s的前n个字符第一次位置
int find(const char c, int pos = 0)const;			//查找字符c第一次出现的位置,从pos开始查找
int rfind(const string & str, int pos = npos)const;	//查找str最后一次出现的位置,从pos开始查找
int rfind(const char* s, int pos = npos)const;		//查找s最后一次出现的位置,从pos开始查找
int rfind(const char* s, int pos, int n)const;		//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos = 0)const;			//查找字符c最后一次出现的位置,从pos开始查找
string & replace(int pos, int n, const string & str);	//替换从pos开始n个字符为字符串str
string & replace(int pos, int n, const char* s);	//替换从pos开始n个字符为字符串s

string字符串比较:
int compare(const string & s) const;	//与字符串s比较,相等则返回 0 
int compare(const char* s) const;		//与字符串s比较

string字符存取:
char & operator[](int n);				//通过[]方式获取字符
char & at(int n);						//通过at方式获取字符

string插入和删除:
string & insert(int pos, const char*s);				//在pos处插入字符串 
string & insert(int pos, const string & str);		//在pos处插入字符串
string & insert(int pos, int n ,char c);			//在pos处插入n个c字符
string & erase(int pos, int n = npos);				//删除pos开始的n个字符

string子串:
string substr(int pos = 0; int n = npos) const;		//返回有pos开始的n个字符组成的字符串


vector容器:
vector构造函数:
vector<T> v;					//采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());		//将v[begin(), end())区间中的元素拷贝给本身
vector(n, elem);				//构造函数将n个elem拷贝给本身
vector(const vector & vec);		//拷贝构造函数

vector赋值操作:
vector & operator=(const vector &vec);		//重载等号操作符
assign(beg,end);		//将[beg,end)区间中的数据拷贝赋值给本身
assign(n,ele);			//将n个elem拷贝赋值给本身

vector容量和大小:
empty();				//判断容器是否为空;
capacity();				//容器的容量
size();					//返回容器中的个数
resize(int num);		//重新指定容器的长度为num,若容器变长,则以默认值0填充新位置
						//如果容器变短,则末尾超出容器长度的元素被删除
resize(int num, elem);	//重新指定容器的长度为num,若容器变长,则以elem值填充新位置
						//如果容器变短,则末尾超出容器长度的元素被删除

vector插入和删除:
push_back(ele);					//尾部插入元素ele
pop_back();						//删除最后一个元素
insert(const_iterator pos, ele);//迭代器指向位置pos插入元素ele
insert(const_iterator pos, int n,ele);	//迭代器指向位置pos插入n个元素ele
erase(const_iterator pos);		//删除迭代器指向的元素
erase(const_iterator start, const_iterator end)	//删除迭代器从start到end之间的元素
clear();						//删除容器中所有的元素

vector数据存取:
at(int idx);		//返回索引idx所指的数据
operator[];			//返回索引idx所指的数据
front();			//返回容器中第一个数据
back();				//返回容器中最后一个数据元素
 
vector互换容器:
swap(vec);					//将vec与本身的元素互换
vector<int>(vec).swap(vec)	//收缩内存 

vector预留空间:
reserve(int len);		//容器预留len个元素长度,预留位置不初始化,元素不可访问


deque容器:
	·双端队列。可以对头端和尾部进行插入删除操作
deque与vector的区别:
	·vector对于头部插入删除效率低,数据量越大,效率越低
	·deque相对而言,对头部的插入删除速度比vector快
	·vector访问元素的速度会比deque快,这和两者的内部实现有关

deque内部工作原理:
	deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
	中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

·deque容器的迭代器也是支持随机访问的

deque构造函数:
deque<T> deqT;					//采用模板实现类实现,默认构造函数
deque(deq.begin(), deq.end());	//将deq[begin(), end())区间中的元素拷贝给本身
deque(n, elem);					//构造函数将n个elem拷贝给本身
deque(const deque & deq);		//拷贝构造函数

vector赋值操作:
deque & operator=(const deque &deq);		//重载等号操作符
assign(beg,end);		//将[beg,end)区间中的数据拷贝赋值给本身
assign(n,ele);			//将n个elem拷贝赋值给本身

deque和大小:			//deque是没有容量(capacity)的概念的 
empty();				//判断容器是否为空;
size();					//返回容器中的个数
resize(int num);		//重新指定容器的长度为num,若容器变长,则以默认值0填充新位置
						//如果容器变短,则末尾超出容器长度的元素被删除
resize(int num, elem);	//重新指定容器的长度为num,若容器变长,则以elem值填充新位置
						//如果容器变短,则末尾超出容器长度的元素被删除
						
deque插入和删除:			//pos的位置是迭代器,eg: deque.begin(),deque.end()
push_back(ele);				//尾部插入元素ele
push_front(ele);			//头部插入元素ele	
pop_back();					//删除最后一个元素
pop_front();				//删除第一个元素
insert(pos, ele);			//在pos位置插入一个ele元素的拷贝,返回新数据的位置 
insert(pos, n, ele);		//在pos位置插入n个ele数据,无返回值 
insert(pos, begin, end);	//在pos位置插入[begin,end)区间的数据,无返回值 
clear();					//删除容器中所有的元素
erase(begin, end)			//删除[begin,end)区间的数据,返回下一个数据的位置 
erase(pos);					// 删除pos未知的数据,返回下一个数据的位置 

deque数据存取:
at(int idx);		//返回索引idx所指的数据
operator[];			//返回索引idx所指的数据
front();			//返回容器中第一个数据
back();				//返回容器中最后一个数据元素

deque排序
#include <algorithm> 
sort(iterator begin, iterator end)	//对begin到end区间内的元素进行排序
	//对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序  
	
stack容器:
概念:stack是一种先进后出(First in Last out, FILO)的数据结构,它只有一个出口

常用接口:
构造函数:
stack<T> stk;				//stack采用模板实现,stack对象默认构造形式
stack(const stack &stk);	//拷贝构造函数

赋值操作:
stack & operator=(const stack &stk); 	//重载=操作符

数据存取:
push(elem);					//向栈顶添加元素
pop(); 						//从栈顶移除第一个元素
top();						//返回栈顶元素
empty();					//判断堆栈是否为空
size();						//返回栈的大小

queue容器:
概念:Queue是一种先进先出(First in First out, FIFO)的数据结构,它有连个出口 
常用接口:
构造函数:
queue<T> que;				//queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que);	//拷贝构造函数

赋值操作:
queue & operator=(const queue &que);	//重载=操作符

数据存取:
push(elem);					//往队尾添加元素
pop();						//从对头移除第一个元素
back();						//返回最后一个元素
front();					//返回第一个元素
empty();					//判断队列是否为空
size();						//返回队列大小 

list容器:
功能:将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:
	链表是由一系列结点组成
结点组成:
	一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环列表

优点:
	采用动态分配,不会造成内存浪费和溢出
	链表执行插入合入删除操作十分方便,修改指针即可,不需要移动大量元素 
缺点:
	链表灵活,单数空间(指针域)和时间(遍历)额外耗费较大 
LIst的重要性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

list构造函数:
list<T> lst;				//list采用模板类实现,对象的默认构造形式
list(begin, end);			//构造函数将[beg, end)区间中的元素拷贝给本身。
list(const list &lst);		//拷贝构造函数
list(n, elem);				//构造函数将n个elem拷贝给本身
list的赋值和交换:
assign(begin, end);					//将[begin, end)区间中的数据拷贝赋值给本身
assign(n, ele);						//将n个elem拷贝赋值给本身
list& operator=(const list &lst);	//重载等号操作符 
swap(lst);							//将lst与本身元素互换

list大小操作:
size();				//返回容器中元素的个数
empty();			//判断容器是否为空
resize(num);		//重新指定容器的长度为num,若容器变长,则以默认值填充新位置
					//如果容器变短,则末尾长处容器长度的元素被删除
resize(num ,elem)	//重新指定容器的长度为num,若容器变长,则elem填充新位置
					//如果容器变短,则末尾长处容器长度的元素被删除 

list插入和删除:
push_back(elem);		//在容器尾部添加一个元素
pop_back();				//删除容器中最后一个元素
push_front(elem);		//在容器开头插入一个元素 
pop_front();			//从容器开头移除第一个元素		
insert(pos, elem);		//在pos位置插入elem元素的拷贝,返回新的数据位置
insert(pos, n, elem);	//在pos位置插入n个elem元素的拷贝,无返回值
insert(pos, begin, end);//在pos位置插入[begin, end)区间的数据,无返回值
clear();				//移除容器中的所有数据
erase(begin, end);		//删除[begin, end)区间的数据,返回下一个数据的位置
erase(pos);				//删除pos位置的数据,返回下一个数据的位置
remove(elem);			//删除容器中所有的与elem值匹配的元素 

list数据存取,排序,反转:
front();				//返回第一个元素
back();					//返回最后一个元素
reverse();				//反转链表
sort();					//链表排序

set/multiset容器:
set基本概念:
	所有元素都会在插入时自动排序
本质:
	set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
	set不允许容器中有重复元素
	multiset允许容器中有重复元素
	
set构造和赋值:
set<T> st;						//默认构造函数
set(const set &st);				//拷贝构造函数

set & operator=(const set &st);	//重载等号操作符 

size();			//返回容器中元素的数目
empty();		//判断容器是否为空
swap(st);		//交换两个容器 

set插入和删除:
insert(elem);			//在容器中插入元素
clear();				//清除所有元素
erase(pos);				//删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(begin, end);		//删除区间[begin, end)的所有元素,返回下一个元素的迭代器
erase(ele);				//删除容器中值为ele的元素

set查找和统计:
find(key);		//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回,set.end();
count(key);		//统计key的元素个数

pair对组:
pair<type,type> p (value1, value2);
pair<type,type> p = make_pair(value1, value2);

set容器排序:
自定义的数据类型,都要指定排序规则
仿函数

map/multimap容器:
map基本概念:
	map中所有元素都是pair
	pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
	所有元素都会根据元素的键值排序
本质:
	map/multimap属于关联式容器,底层结构是二叉树实现
优点:
	可以根据key快速找到value值
map和multimap的区别:
	map不容许容器中有重复key值元素
	multimap允许容器中有重复的key值元素

map构造函数和赋值:
//map中所有元素都是成对出现,插入数据的时候要使用对组
map<T1, T2> mp;					//map默认构造函数
map(const map &mp);				//拷贝构造函数
map& operator=(const map &mp);	//重载等号操作符

map的大小和交换:
size();				//返回容器中元素的数目
empty();			//判断容器是否为空
swap(mp);			//交换两个集合容器

map插入和删除:
insert(elem);		//在容器中插入元素elem
clear();			//清除所有元素
erase(pos);			//删除pos迭代器所指的元素,返回下一个元素
erase(begin,end);	//删除区间[begin, end)的所有元素,返回下一个元素的迭代器
erase(key);			//删除容器中值为key的元素

map查找和统计:
find(key);			//查找key是否存在,若存在,则返回该键的元素的迭代器;若不存在,返回set.end()
cout(key);			//统计key元素的个数

map容器排序:
map容器默认排序规则为:按照key值进行 从小到大排序
利用仿函数,改变排序规则

*黑马程序员c++课程学习笔记

猜你喜欢

转载自blog.csdn.net/Fighting_gua_biu/article/details/113771574