C++编程思想——模板与泛型

来源:互联网 发布:qq飞车月光女神数据 编辑:程序博客网 时间:2024/06/11 19:34

模板与泛型

一、模板

1、在默认的模板参数中,只能够被定义一次,而且它之后的模板参数也必须有默认值,这点与函数有点类似。

2、Vector的模板声明为:template<class T,class Allocator=allocatot<T> > class Vector;,第二个参数代表vector使用的分配器,负责内存的分配、释放、自动回收等。

3、Typename可以用于取代class以及声明模板代码内部某个类型。如果没有的话,编译器将会将那个类型看作一个静态的数据类型。

4、函数模板是一种抽象的函数定义,代表一类同构函数,它的实例化是由编译程序在处理函数调用时自动完成的;而类模板具有更高的抽象的类定义,其实例化必须由程序员在程序中显示的指定。

5、泛型编程可以写一般化的代码,效率与针对某特定数据类型而设计的算法相同。使用泛型编程可以增加代码的重用性,但是容易产生代码膨胀。

6、模板特化,分为类模版以及函数模板的特化。当函数模板需要对某些类型进行特别处理时为函数模板的特化。类似的可以定义类模板。

 

二、STL

1、STL是提供对常用需求重新开发的一种替代方法。包括容器、算法、迭代器。STL就是泛型编程的例子。

2、容器:

C++提供的3中容器分别为:序列容器:vectorlistdeque;容器适配器:queuestackpriority_queue;关联式容器:setmapmultimapmultiset

1) vector连续的对象数组。支持随机访问,动态数组的内存不够时,动态重新分配,其内存一般是当前的两倍。插入操作的开销很大。利用迭代器插入元素可以使用Insert函数。由于重新分配带来的问题,以后那次,如果在程序的某一处创建所有的对象看,而在另一处随机访问它们,可以先填充一个deque,然后在该deque的基础上创建一个vector,达到快速索引的目的。因为一旦内存不够进行重新分配的时候,其迭代器也会无效,所以确定元素大小下使用vector最安全,且一次性的填入所有的元素另只在后端添加或者删除元素。

2) deque,双端队列。利用的是多个连续的存储块,所以向其两段添加或删除元素带来的开销很小。支持随机访问,但是需要分配新的空间是速度很快,因为它的元素是连续的几块内容。可以很方便在前端和后端加进新的元素。

3) List双向链表,在序列的任何地方都可以快速的插入或删除元素,它只要在存储区顶部设置一个前向和反向指针,开销小。

小结:这三种容器都有push_back函数,但是push_front函数是后面两种特有的。检索元素的时候12可以使用[]sortreverselist有其内部的成员,通用的这两种算法仅仅适用于普通的数组、vectordeque。为了提高效率,vector在添加元素前最好利用reserve设置容量,deque是不需要的,vector是没有pop_front函数的。

4)关联式容器底层的机制都是红黑树。set情况下,要查看对象是否以及将那个在几何中,而使用map时查看关键字。但是如果使用operatorp[]查询一个值,但是该值不存在,map就会创建一个新的关键字对。所以想查找某个对象是否在几何终会难过,应该使用count或者是find函数。

5)map中将关键字以及值插入是以pair作为实例化的一部分来创建的。该pair成为value_type,所以其实是创建了一个value_type对象。

6)多重集合可以允许重复。

7)适配器容器都有一个该适配器构建在其上的默认的容器。所有适配器默认的序列容器都是vector

8)智能指针auto_prt保证当异常掷出后,分配的对象可以自动销毁,内存被释放。是在动态内存和异常之间进行平滑的交互。std:auto_ptr<char> ptr(new char[10]),后面的尖括号中必须制定智能指针的类型。其实现的方式在于引用计数的判定。

3、算法

1)unique算法仅仅将毗邻的重复元素删除,如果去掉重复的元素,必须先排序。

2)删除时,erase才能够实现真正的删除,而remove只是将元素放入容器的后面,重新设置了迭代器的end指针,返回指向新末尾的迭代器。

3)使用库函数back_inserter能够返回一个特殊类型的迭代器,内存的大小可根据容器的需要自动扩大。

4)Copyremove_copy_if。复制定义好的某个序列中的一个子集到另一个序列中。

5)Replace_copy_if,输出一个序列时用一个固定的值来替代这些元素。

6)Count_if返回一个徐行列中国满足给定判定函数的元素的个数、

7)函数对象。是重载operator()的类的一个实例。根据使用参数的个数和返回值的类型分为发生器、一元函数、二元函数,一元判定函数,其返回值是bool型一元函数。二元判定函数。函数对象可以用来解决函数参数个数的问题。更具体的可以使用bind1stbind2st函数适配器,将二元函数对象转换为一元函数对象。

8)Fill可用一个特定只来填充容器中某个范围的数据。Generate()为范围内的每个元素进行gen()调用,为每个元素 产生一个不同的值。

9)Reverse倒置原序列范围内的元素,reverse_copy会保持原序列范围内元素序列不变,将倒置的元素复制到destination中,返回超越末尾的迭代器。Rotate则是旋转,以中间元素为界限。

10)Find查找,search是针对子集。

11)Sort排序,部分排序partial_sort

 

4、迭代器

迭代器的种类有:输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器。最后一种可以利用operator[]进行索引,而双向迭代器每次只能走一个位置。

 

0 0