【GeekBand】stl首周

2016-06-19  本文已影响0人  05a6cfdfab37

1.C++模板简介

1.模板概观

模板是c++的一种特性,允许函数或类(对象)通过泛型的形式表现或运行

c++通常使用两种模板
a.类模板,使用泛型参数的类
b.函数模板,使用泛型参数的函数

2.函数模板

template<typename T>
inline T Max(T a,T b)
{
    return (a > b)?a:b;
}

从语法上讲,class和typename没有区别,但不能使用struct; 尽量使用typename; 模板实例化,编译器自动的; 如果该型别不支持函数所使用的操作,会报错; (比如std::complex没有重载>,但函数里使用了complex类的>) 模板会被编译两次,一次是本身,一次是调用时候的实例化; 参数推导,每个T必须严格匹配,不允许自动类型转换; 比如Max(1,2.0); 解决1:用static_cast或强制转换:Max(static_cast(1),2.0) 解决2:显式指定T的类型:Max(1,2.0)//1可以转换成double 函数模板可以像普通函数一样重载,可以重载同名的非模板函数; Max('a',4.2)参数类型不同,当存在非模板函数时,会调用非模板函数进行类型转换; 重载版本的声明必须位于调用位置之前;

3.类模板

类也可以通过参数泛化,从而可以创建出一族不同类型的类实例(对象);
类模板实参可以使某一型别或者常量(仅限int或enum);
在内部T像其他类型一样定员成员变量和成员函数;
如果类模板中需要使用到这个类模板本身,应该使用其完整定义,带<...>的形式;
Stack >两个尖括号不要连到一起,会编译成<<,经过验证,新版编译器不会出现该问题;
类模板特化,要把所有成员函数都重写一遍;可以添加新的成员函数;

偏特化:

template <typename T1,typename T2>class MyClass{...};
template <typename T> class MyClass{...};    偏特化成同类型;
template <typename T>class MyClass<T,int>{...};  偏特化成非泛型;
template <typename T1,typename T2>class MyClass<T1*,T2*>{...};   偏特化成指针;

如果调用同等的匹配不止一个偏特化,二义性,编译器不会通过;
如下所示:

MyClass<int,int>; //可同时匹配2,3同类型和参数2偏特化为int
MyClass<int*,int*>; //可同时匹配2,4同类型和指针

类模板参数可以有默认值,如下:

template<typename T,typename TContainer = std::vector<T>>
class stack
{
    private:TContainer m_Container;
}

2.泛型编程

1.概观

泛型编程是一种编程方法,这种方法将型别(type)以一种to-be-specified-later的方式给出,等到需要调用时,再以参数方式,通过具体的、特定的型别实例化一个具体的方法或对象
泛型编程是一种编程想法或思维,并不依赖于具体语言

2.特性 Traits

A[0],A[1],A[2].....A[n]

如何构建型别为T的初始类型,姑且使用T(0);
如果求和函数,求出的结果超出了类型的容量,
比如char数组”abc“,求和的值大于char类型容量255
会溢出overflow,此时可以强制使用来储存,或者使用Traits; Sigma函数的返回值的型别叫做T的trait;

T -> association -> characteristic of T -> another type -> trait;

Traits可以实现为模板类,而关联(association)是针对每个具体型别T的特化;
在这个例子里traits命名为Sigma Traits,叫做traits模板(traits template);
Traits可以实现为模板类;

template class SigmaTraits{};
template<>class SigmaTraits{
    public: typedef int Return Type;}   //当传进去的是char,return的类型变成int;

把每个传入类型都指定return的类型;
typename SigmaTrais::ReturnType //这一串是返回类型的写法;
3.迭代器

本身是一个对象,指向另一个(可以被迭代的)对象;
算法通常以迭代器作为输入参数;

3.容器

1.Vector

存放任意型别的动态数组;数据结构和操作与数组类似,在内存中是一段地址连续的空间;
Vector支持动态空间大小调整,随着元素的加入,vector内部会自动扩充内存空间;
头文件vector,名称空间std;
2.创建

创建一个T型别的空vector:    vectorv;
创建一个容量是n的T型别vector: vectorv(n);
创建一个容量是n的T型别vector,并且都初始化为i:    vectorv(n,i);
创建一个已有v的拷贝: vectorcopyOfV(v);
通过一个数组创建一个vector:   int array[]={1,2,3,4,5,6,7};
    vectorv(array,array+10);

3.方法

调用push_back函数,表示将元素添加至其尾部:
判断是否为空:empty();
获取大小:size();
访问:


vector::at();   越界会抛出exception,但效率不如operator;
vector::operator[]; 不做边界检查,但访问效率高;

删除:

clear:清除整个vector;
pop_back:弹出vector尾部元素;
erase:删除vector中某一位置的元素
        用法一:指定删除某一元素,v.erase(it+1); //t位置+1的位置的元素;
        用法二:删除指定的满足某条件的;

对象里面重载了operator()的话,调用方法像函数一样;

  1. Deque

能存放任意型别的双向队列,新增了两个方法:

push_front: 在头部插入一个元素;
pop_front: 在头部弹出一个元素;

5.List
存放任意型别的双向链表(double linked list); 有next和prev指针指向前一个和后一个元素; 头文件list和名称空间std;
优势: 弹性,可以随意插入和删除元素,只需要改变next和prev的指针链接; 对于移动元素到另一个list,没有发生复制;
劣势: 只能以连续的方式存取list中的元素,查找任意元素的平均时间和list长度成线性比例; 对于查找、随机存取等元素定位操作,效率低; 在每个元素节点上增加一些较为严重的开销,即向前向后两个指针;

上一篇 下一篇

猜你喜欢

热点阅读