STL模板库介绍

一、模板技术

是一种自动生成代码的技术,能够让代码在编写时不需要考虑数据类型(让代码脱离数据类型),所以这种技术也叫泛型编程技术。

二、为什么使用模板

1、C/C++是一种静态编程语言(预处理->汇编->编译->链接),静态编程语言的优点是运行速度快,而缺点是实现通用的代码比较麻烦,例如:实现一个通用的快速排序算法。
2、借助回调函数实现通用代码,实现难度高且使用麻烦。
3、借助宏函数实现通用代码,但类型检查不严格、没有返回值、容易出错。
4、借助函数重载机制实现通用代码,缺点是代码段会大量增加,但不能解决未知的类型。
5、综合以上原因,C++之父在C++中实现模板技术,从而让C++彻底脱离数据类型。
注意:typename 和 class 可以通过

三、函数模板

1、函数模板的定义

template <typename T1,typename t2,...>
T3 函数名(T1 arg1,T2 arg2)
{
    T3 ret = arg1+arg2;
    return ret;
}
    
可以使用任何名字作为类型名,但使用"T"俗成约定,它表示该函数指定的是任意类型。

2、函数模板的原理

模板函数会经历两次编译:
        1、检查模板的语法是否正确,但此时并不会生成二进制的指令。
        2、根据调用者提供的参数类型再次检查模板代码,如果没有错误再生成二进制指令(函数代码)。

3、函数模板的调用

C++编译器并不会把模板函数当用一个函数实体,而一个能够生成函数实体的工具,它能够根据调用者提供的数据类型生成出不同函数实体。
根据调用者提供的数据类型生成函数实体的过程叫实例化。
实例化的方式:
        自动实例化:根据实参的数据类型,自动实例化。
        显式实例化:函数名<类型参数>(实参),当函数的参数与模板类型参数没有关系时只能显式;

4、默认形参

    template <typename T1,typename t2=int>
    T3 函数名(T1 arg1,T2 arg2)
    {
        T3 ret = arg1+arg2;
        return ret;
    }
    可以像函数的默认形参一样,给模板设置默认的类型。
5、模板的特化
    模板虽好但并不能解决所有问题,有些特殊类型与普通的运算规则不同,需要给它实现一个特殊的版本,如:char* 类型。
    当模板函数与普通函数重名时不会冲突,会优先调用普通函数。

四、类模板

1、类模板的定义

template <typename T,typename M,typename R>
class Test
{
    M m_num;
public:
    Test(T t)
    {
        m_num = t;
    }
    R func(void)
    {
        R ret;
        return ret;
    }
};

2、类模板的使用

    类模板也需要先实例化再使用,与函数模板不同的是它支持自动实例化,必须显式的指定类型参数实例化。
    类名<类型,...> 对象;
    类模板的实例化过程:
    编译期:编译器将类模板实例化为类,并生成创建类对象的指令。
    运行期:处理器执行创建类对象的指令,将实例化完成的类创建为对象,而类模板的成员只有对象调用时才实例化(谁调用谁实例化)。
    注意:类模板是一种编译时的多态。

3、类模板的静态成员

    类的静态成员在类中声明,在类外定义,在类模板中也一样,但与普通类的静态成员不同,它需要模板说明。
template <typename T,typename M,typename R>
class Test
{
    static int num;
    M m_num;
public:
    Test(T t)
    {
        m_num = t;
    }
    R func(void)
    {
        R ret;
        return ret;
    }
};
template <> 类型 类名<类型参数>::成员名;

4、递归实例化

    类模板的参数可以是任何类型,只要该类型提供了模板所需要的功能。
    实例化后的类模板已经是一个有效的类型了,所以它也可以当做类模板的参数来实例化类模板,我们把这种实例化叫递归实例化;
    Test<Test<int>> t;
    vector<vector<int>> arr;

5、类的局部特化

    当某个成员函数不能做到通用,需要实现一个特殊的版本,这情况叫类的局部特化,这种局部特化函数需要在类外实现。
    template<> 返回值类型 类名<类型>::函数名(参数列表)
    {
        函数体;
    }

6、全类特化

    当需要针对某种特殊类型实现一个特殊版本的类,这怀情况叫类的全特化。
    template<> 类名<类型>
    {

    };

7、类模板的默认参数

    类模板与函数模板一样也可以设置类型的默认参数。
    规则与函数默认形参基本一致(设置缺省类型的靠右)。
    template <typename T1,typename T2=int>
    class 类名
    {

    }

    template <typename T1,typename T2=T1>
    class 类名
    {

    }
    缺省值可以使用前面的类型。

五、STL模板库

STL是Standard Template Library的缩写,中文名称标准模板库,由惠普实验室提供,共有三类内容:
容器:也就是以类模板形式实现的数据结构。
算法:也就是以函数模板形式实现的一些算法,如:max
min、find、sort、swap。
迭代器:容器的成员,用于帮助访问容器中的数据,使用方法类似于指针。

向量容量:vector 
    头文件:vector
    采用顺序的内存存储数据,可以通过下标随机访问,也叫数组容器。
    优点:会随着元素的增加而自动扩展内存(在原有的基础上扩展一倍),所以也叫智能数组。
    支持的运算符:
        ==、!=、<=、>=、<、>、[]
    常用的成员函数:
        at() 功能相当于[]运算符,但比[]更安全,使用at越界访问时会产生异常,而[]越界访问结果是未知的。
        back() 返回末尾的最后一个元素
        begin() 返回一个正向迭代器,指向第一个元素。
        end() 返回一个正向迭代器,指向最后一个元素的下一个位置。
        capacity() 返回在不重新分配内存前容器的容量。
        erase() 删除元素,参数必须是自己的迭代器。
        insert() 指定的位置插入元素,该容器的插入操作效率比较低,不建议使用。
        pop_back() 删除最后一个元素
        push_back() 在末尾添加一个元素
        rbegin() 返回一个逆向迭代器,指向最后一个元素。
        rend() 返回一个逆向迭代器,指向第一个元素的上一个位置。
        size() 返回元素的数量
        max_size() 能容纳元素的最大值

链表容器:list
    头文件:list
    是一个功能齐全的链表容器,是最常用的容器之一。
    它有排序的成员函数,所有元素要它存储的元素必须支持<运算符。
    成员函数:
        merge() 合并两个链接。
        remove() 按值删除元素。

栈容器:stack
    头文件:stack
    实现了栈结构的基本功能,采用链式存储,没有迭代器,是一种FILO(先进后出)结构。
    支持的运算符:
          ==、<=、>=、<、>、!=

队列容器:queue
    头文件:queue
    实现了队列结构的基本功能,采用链式存储,没有迭代器,是一种FIFO(先进先出)结构。

优先队列容器:priority_queue
    头文件:queue
    在队列的基础上,对入队的元素进行排序,然后按照排序后的结果进行出队(权重大的优先),底层采用链式存储结构,要求它存储的元素必须支持<运算符,不支持迭代器。

双向队列容器:deque
    头文件:queue
    使用方法与向量类似,它允许在头和尾快速添加、删除元素。
    支持的运算符:[]

集合容器:set
    头文件:set
    特点是元素不能重复,且会自动排序,要求它存储的元素必须支持<运算符,并且只能使用迭代器遍历。
    成员函数:
        count() 获取某个元素的数量,结果只能是0或1。
        earse() 删除元素,即可以按值删除,也可以使用迭代器删除。
        find() 查找元素,如果找到返回指向该元素的迭代器,找不到返回end()。
        lower_bound() 返回大于等于key值的第一个元素迭代器。
        upper_bound() 返回大于key值的所有元素的迭代器。

多元集合容器:multiset
    头文件:set 
    元素可以重复,会自动进行排序,要求它存储的元素必须支持<运算符。
    成员函数:
    equal_range() 返回与给定值相等元素迭代器范围。
    remove_if() 按条件删除,所谓的条件就一种判断函数
        bool 函数(元素类型)
        {
            if(条件)
                return true;
            else 
                return false;
        }
    splice() 把链表连接到指定的位置。
    unique() 删除链表中的重复元素。

映射容器:map
    头文件:map
    是一种由 key/value 组成元素(字典)的容器,要求是key不能重复,会根据key自动进行排序。
    key就相当于下标,可以当作访问value的凭证,它的底层采用红黑树存储,因此它的查找效率极高。
    支持的运算符:[],之所支持是因为key不能重复。
    成员函数:
        erase() 可以使用key或迭代器删除。
        insert() 插入元素,可以按位置插入,也把一个迭代器的范围插入进去,注意:元素是以pair形式插入的。
            pair<key_type,value_type> p(key,value);
        lower_bound() 返回和第一个大于等于key的元素的迭代器。
            返回的迭代器是指向 pair类的元素,因此使用first,second来访问。
        upper_bound() 返回和第一个大于等于key的元素的迭代器。

多重映射容器:multimap
    头文件:map
    也是一种由 key/value 组成元素(字典)的容器,也会根据key自动进行排序,与map不同的是它的key可以重复。
    成员函数:
        count() 返回键值等于key的元素个数。
        equal_range() 返回键值为key所有元素。
        erase() 可以使用key或迭代器删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值