您的位置:首页 > 编程语言

《STL 源码剖析读书笔记(一)》-----迭代器概念与trais编程技法

2013-07-20 11:19 597 查看

STL源码剖析读书笔记

目录

一.迭代器

1. 迭代器的定义 2. 为什么需要迭代器 3. 迭代器工作原理 4. 迭代器的分类

二.Traits编程技法

1. 为什么需要Traits编程技法? 2. Traits编程技法原理 3. iterator_traits剖析 4. std::iterator的约定 5. 扩展,SGI STL的__type__traits

三.总结

正文 一.迭代器 1.迭代器的定义 迭代器是一种抽象的设计概念,迭代器是一种数据结构,提供统一方法(如遍历,获取元素)对容器内部的元素进行操作,而又无需暴露容器元素的内部表达方式。 举个例子,指针可以看做是数组的迭代器(尽管不太符合STL规范),但是指针有很多种,我们可以提供一个封装来解决这个问题 template<tyname PtrType> class Proxy { PtrType* ProxyPtr; //…… } 通过模板,我们用Proxy这个类统一了指针 Proxy<int>就是int指针Proxy<string>就是string指针 它提供了统一的操作(取地址,随机访问)不管什么类型数组,反正都是用Proxy<PtrType>取地址,地址上的值就是数组内对应的元素,指针p+n对应的就是数组第n个元素,不管p是什么类型指针。 也就是说,迭代器是一类对象(不管Proxy特化为什么类型指针,都是Proxy类,都是针对数组这个容器),有着统一的方法与针对不同容器特定的行为,对容器进行操作,而不论容器类型,使得通用算法通过迭代器对不同容器起同样的效果。不同容器有专有的迭代器,但是这些迭代器都有统一的接口(方法),区别只是这些方法的内部实现不一样。 2.为什么需要迭代器? 迭代器是GP泛型编程的重要组件,是容器与算法重要的胶合剂,多种容器对应多种专有迭代器,但是这些迭代器是外在统一的方法,内在不同的实现。可以对应同一个算法正常运作。没有迭代器,通用算法就没法实现通用。 3.迭代器的工作原理 迭代器的工作原理与指针类型,因为迭代器是对象,通过对操作符*,->的重载,完成对容器\内被指向的元素的获取,通过++,--,operator[]操作符重载,完成迭代器指向下一个元素,上一个元素,随机访问容器内元素。 例如STL的通用算法find(begin,end,value); template<typename T> Iterator find(Iterator begin, Iteratorend,const T& value) { While(begin!=end&& *begin != value) ++begin; Return begin; } 假设这里的iterator是一个指针,那么久很好理解了,第一个参数是指向某一个容器头部的指针,第二个参数指向容器尾部的指针,value是要搜索的值,find要搜索的value就返回指向容器内部那个值的指针。 对于内置数据类型的顺序容器,很多就可以像我那个proxy<PtrType>这样封装一下就是个迭代器,放到这个算法里面也没有问题。如果是关联容器,底层是树,哈希表这样的数据结构,为了也能满足这个算法,很明显不能用原始的指针了,需要对++ *->这些运算符重载,指定遍历树中的元素顺序,来模拟普通的顺序遍历,从而满足find这样的算法。 1. 迭代器的分类 对于STL,内置的迭代器相应的可以划分为这么几个类型:
迭代器类型说明
Input Iterator 这种迭代器所指对象是只读的,迭代器取出所指的值,可以访问下一个元素,判断是否到达最后元素,支持操作 *p(返回值不允许修改),++p,p++,p!=q,p==q
Output Iterator 和Input Iterator迭代器类型,不过返回值允许修改,支持*p,++p,p++,p!=q,p==q的操作
Forward Iterator 前向迭代器,和Output Iterator支持操作一致
Bidirectional Iterator 双向迭代器,Forward Iterato支持的操作都支持,还支持--p,p--.
Random Access Iterator 随机访问迭代器,Bidirectional Iterator支持的操作都支持,另外还支持 operator[ ] 随机访问容器内元素
迭代器分类表 从左到右,迭代器越来越高等不同算法对所需要的迭代器有要求,不过根据STL的算法参数命名规则,以算法能接受的最初等的迭代器类型来为参数命名,也就是说,接受Input Iterator类型参数的算法肯定也支持Random Access Iterator类型的参数。 二.Traits编程技法 1.为什么需要Traits编程技法? STL的算法分通用算法和专有算法,对于有些容器,由于容器特殊,用通用算法比较耗时,为了提高效率,又针对这一容器编写了专有的算法来优化效率。 对于算法来说,如果知道操作的迭代器所指对象的类型,可以根据所指对象的不同类型,进行不同的优化。从而提高算法的效率。例如copy算法,如果知道是元素是POD类型(POD类型指在内存布局上与C兼容的类型,可以用memcpy直接拷贝对象),可以直接用memcpy(),对于是char*的类型封装的迭代器,甚至可以用memmove()函数来优化效率。 2. Traits编程技法原理 那么,一个关键性问题,对于通用算法,获取到的信息只有迭代器本身的信息,它如果知道迭代器所指对象的类型呢?毕竟C++不支持C#的typeof,而typeid属于RTTI,不能用来声明变量,而且RTTI的效率不高,那么为了解决这个问题,就诞生了Traits编程技法。Traits在英文中是特征的意思,根据事先约定的迭代器编写规则,在迭代器类中给出足够的所指对象信息,在通用算法中获取迭代器所指对象的信息。 对于一个迭代器类,列如一开始举得例子模板类Proxy,在实例化的时候,模板参数PtrType就是这个array容器的迭代器所指的元素类型。那么我们可以在Proxy中内嵌类型声明。这样在Proxy模板外我们可以用typename 调用模板类作用域下属的内嵌类型。 例如 template<tynamePtrType> class Proxy { typedef T value_type; PtrType* ProxyPtr; //…… } 在Proxy类模板类外面 template<typenameIterator> void Find(Iteratora) { typedef typename Iterator::value_type Value_type//可以用typename来获取所指对象的类型,搭配typedef来声明新类型。 Value_type test; //用迭代器所指对象的类型来声明变量 } Int main() { Proxy<int>iter; Find(iter); } 对于自定义迭代器,可以通过在迭代器内内嵌声明来解决问题,但是对于原生指针的迭代器,如何在Find函数内获取声明呢,这里可以通过增加一个间接层代理类iterator_traits来解决问题。 对于自定义的迭代器,因为已经内嵌声明了,所以有 template<typename T>//自定义迭代器 T是传入的类型class Iterator{public: typedef T value_type;protected:private: T* iter;};template<typename Iterator>struct Iterator_traits{ typedef Iterator::value_type value_type;};对于原生指针作为迭代器的,可以使用模板偏特化来解决。模板偏特化指需要根据模板的某些但不是全部的参数进行特化,就解决了原生指针的迭代器获取指向对象的类型的问题了。如下template<typename T>//T是一个原生指针class Iterator_traits<T*>{public: typedef T value_type;protected:private:};那么通用算法的find()应该改写成这样template<typename Iterator,typenameT>typename iterator_traits<Iterator>::value_typeFind(Iterator begin, Iterator end,const T& Value){ /*…………*/} 现在,不论是原生指针还是封装过的自定义迭代器,都可以通过iterator_traits获取正确的指向对象的类型。3. iterator_traits剖析 实际上,SGI STL的源码内,Iterator_traits类可以获取的信息是非常丰富的,如struct iterator_traits{ typedef typename::I::iterator_categoryiterator_category; typedef typename::I::value_typevalue_type; typedef typename::I::difference_typedifference_type; typedef typename::I::pointerpointer; typedef typename::I::referencereference;};下面一一解释。(1) value_typevalue_type是指迭代器所指对象的的类型,任何一个自定义迭代器,都应该内嵌value_type类型。做法如上节所述 (2) difference_typedifference_type是定义两个迭代器之间距离的变量的类型。也可以作为保存容器最大容器的变量类型。如果一个泛型的通用算法提供计数功能,那应该是这样的 template<typename I,typenameT>typename::iterator_traits<I>::difference_type count(I begin,I end,const T& Value){ typename::iterator_traits<I>::difference_type n= 0; for (;begin!=end;++begin) { if (*begin == Value) { n++; } } return n;}对于原生指针,C++内建了ptrdiff_t作为原生指针的difference_type(定义在<cstddef>,在VS2010上看,其实就是int) template<typename T>struct iterator_traits<T*>{ typedef ptrdiff_t difference_type; /*………………*/};(3) reference当迭代器需要返回容器内的元素本身来对元素的值进行修改时,即使用具有写入功能的迭代器,就应该在*p时,返回一个p所指元素的引用,那么返回的应该是对象的引用类型,即返回这个reference类型。具体实现的源码在pointer后。 (4) pointer当迭代器需要返回容器内的元素本身来对元素的值进行修改时,即使用具有写入功能的迭代器,就应该在*p时,返回一个p所指元素的引用,既然引用可以,那么用指针也可以,不过指针没有引用安全而已。所以我们可以这样设计template<typename PtrType>//PtrType是原生指针,iterator是自定义迭代器struct iterator{ ... typedef T* pointer; typedef T& reference;};template<typename I>//I是自定义迭代器struct iterator_traits{ ... typedef I::pointer pointer; typedef I::reference reference;};template<typename T>//T是原始指针?struct iterator_traits<T*>{ ... typedef T* pointer; typedef T& reference;};(5) iterator_categoryiterator_category是迭代器所属分类的标示符,具体分类请看一,4.迭代器的分类。 STL的算法是追求效率的极致,为了效率最高,最好是对不同分类的迭代器都有不同的算法优化,如有一个通用算法test。为了通用于5种不同迭代器,一种解决办法就是写5个接受不同种迭代器参数的同名函数,这样即使我的ForwardIterator 和InputIterator的test算法优化一样,我也要复制粘贴两遍,这样才能对ForwardIterator和InputIterator类型的迭代器使用test算法,这是极其违反软件工程的DRY原则的。那么另外一个解决办法可能是这样的 void test(Iterator a){ if (is_InputIterator(a)) //函数能不能设计出来另说,判断是不是InputIterator { } else if(is_OutputIterator(a))//判断是不是OutputIterator { } else if(is_XXXIterator(a)) { } ....}这样的if-else分支选择和判断函数的使用会影响效率,如果使用重载机制来确定使用什么函数的话,就可以在编译器解决这个问题,从而提高算法效率。 编译期解决方案如下,如果iterator_traits能够获取迭代器所属种类的话,就可以在通用算法中加入第三个参数来匹配迭代器种类,通过iterator_traits<I>::iterator_category()作为第三个参数,来确定使用的函数类型,就可以编译期通过函数重载解决大量if-else这个问题。 为了解决同一个算法,因为两个不同迭代器要复制一遍的问题,可以使用派生类的隐式类型转换到基类来做。 解决方案如下,先构造迭代器分类的类型继承链 struct input_iterator_tag{};struct output_iterator_tag{};struct forward_iterator_tag : publicinput_iterator_tag{};struct bidirectional_iterator_tag : publicforward_iterator_tag {};struct random_access_iterator_tag : publicbidirectional_iterator_tag{}; 现在假设一个算法test,对所有迭代器都适用,并且inputforward bidirectional random迭代器的代码相同,那么只要写两个版本的迭代器算法如下。 template<typename InputIterator>void __test(InputIterator a,input_iterator_tag){ }template<typename OutputIterator>void __test(OutputIterator a,output_iterator_tag){ }template<typename InputIterator>void test(InputIterator a){ __test(a,iterator_traits<InputIterator>::iterator_category())}当传入给a的是input迭代器,那么会通过__test()的第二个参数确定重载,确定使用的函数,当传给a的是random迭代器,因为random是input迭代器的派生类,所以为了匹配__test函数。第二个参数会被隐式转换为input基类,然后调用使用input_iterator_tag的函数,这样就解决了违反DRY原则的问题。 下面是SGI iterator的部分源码 // 节录自SGI STL <stl_iterator.h> // 五种迭代器类型 struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag : public input_iterator_tag {}; struct bidirectional_iterator_tag : public forward_iterator_tag {}; struct random_access_iterator_tag : public bidirectional_iterator_tag {}; // 为避免写码时挂㆒漏万,自行开发的迭代器最好继承自下面这个,具体细节后述 std::iterator template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&> struct iterator { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference; }; // 「榨汁机」traits,获取类型信息 template <class Iterator> struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; }; // 针对原生指标(native pointer)而设计的traits 偏特化版。 template <class T> struct iterator_traits<T*> { typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; }; // The overloaded functions iterator_category, distance_type,and // value_type are not part of the C++ standard. (They have been // replaced by struct iterator_traits.) They are included for // backward compatibility with the HP STL. // We introduce internal names for these functions. //这个函数方便确定迭代器类型 template <class _Iter> inline typename iterator_traits<_Iter>::iterator_category __iterator_category(const _Iter&) { typedef typenameiterator_traits<_Iter>::iterator_category _Category; return _Category(); } //这个函数方便确定迭代器之间距离的类型 template <class _Iter> inline typename iterator_traits<_Iter>::difference_type* __distance_type(const _Iter&) { returnstatic_cast<typename iterator_traits<_Iter>::difference_type*>(0); } //这个函数方便确定迭代器所指对象的类型 template <class _Iter> inline typename iterator_traits<_Iter>::value_type* __value_type(const _Iter&) { returnstatic_cast<typename iterator_traits<_Iter>::value_type*>(0); } template <class _Iter> inline typename iterator_traits<_Iter>::iterator_category iterator_category(const _Iter& __i) { return__iterator_category(__i); } template <class _Iter> inline typename iterator_traits<_Iter>::difference_type* distance_type(const _Iter& __i) { return__distance_type(__i); } template <class _Iter> inline typename iterator_traits<_Iter>::value_type* value_type(const _Iter& __i) { return __value_type(__i); } //下面了是利用了重载判断和iterator_traits特性的distance函数和advance函数 template <class _InputIterator, class _Distance> inline void __distance(_InputIterator __first, _InputIterator__last, _Distance& __n, input_iterator_tag) { while (__first !=__last) { ++__first; ++__n; } } template <class _RandomAccessIterator, class _Distance> inline void __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance& __n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __n += __last - __first; } template <class _InputIterator, class _Distance> inline void distance(_InputIterator __first, _InputIterator __last, _Distance& __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __distance(__first,__last, __n, iterator_category(__first)); } #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION template <class _InputIterator> inline typenameiterator_traits<_InputIterator>::difference_type __distance(_InputIterator __first, _InputIterator __last,input_iterator_tag) { typenameiterator_traits<_InputIterator>::difference_type __n = 0; while (__first !=__last) { ++__first; ++__n; } return __n; } template <class _RandomAccessIterator> inline typenameiterator_traits<_RandomAccessIterator>::difference_type __distance(_RandomAccessIterator __first, _RandomAccessIterator__last, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); return __last - __first; } template <class _InputIterator> inline typename iterator_traits<_InputIterator>::difference_type distance(_InputIterator __first, _InputIterator __last) { typedef typenameiterator_traits<_InputIterator>::iterator_category _Category; __STL_REQUIRES(_InputIterator, _InputIterator); return__distance(__first, __last, _Category()); } #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ template <class _InputIter, class _Distance> inline void __advance(_InputIter& __i, _Distance __n,input_iterator_tag) { while (__n--) ++__i; } #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM!= _MIPS_SIM_ABI32) #pragma set woff 1183 #endif template <class _BidirectionalIterator, class _Distance> inline void __advance(_BidirectionalIterator& __i, _Distance__n, bidirectional_iterator_tag) { __STL_REQUIRES(_BidirectionalIterator,_BidirectionalIterator); if (__n >= 0) while (__n--) ++__i; else while (__n++) --__i; } #if defined(__sgi) && !defined(__GNUC__) &&(_MIPS_SIM != _MIPS_SIM_ABI32) #pragma reset woff 1183 #endif template <class _RandomAccessIterator, class _Distance> inline void __advance(_RandomAccessIterator& __i, _Distance__n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __i += __n; } template <class _InputIterator, class _Distance> inline void advance(_InputIterator& __i, _Distance __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __advance(__i, __n,iterator_category(__i)); } __STL_END_NAMESPACE 4.std::iterator的约定 为了符合STL迭代器设计规范,任何迭代器都应该提供这5个内嵌类型。以利于iterator_traits获取类型信息,否则可能无法与其他STL组件顺利搭配。然而谁都有粗心大意的时候,为了让自定义的每一个类都符合规范,STL提供了一个iterator class,只要继承这个类,就可以保证每一个自定义的迭代器都符合规范。 template<class Categroy,class T,class Distance =ptrdiff_t,class Pointer = T*,class Reference = T&>struct iterator{ typedef Categroy iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference;};template<class Ptr>struct MyIter : publiciterator<iterator<forward_iterator_tag>,Ptr >{/*………………………………….*/};5.扩展,SGISTL的__type__traits 在SGI STL中还有一个特有的扩展,TypeTraits,判断传给它的类型是否具有 trivial_default_constructor无用的默认构造函数 trivial_copy_consturctor 无用的拷贝构造函数 trivial_assignment_operator无用的赋值函数 trivial_destructor无用的析构函数 trivial_des1tructor is_POD_type;类型是POD类型 知道这些信息后,我们就可以对类型进行相应的优化,例如,如果传给typeTraits类型是属于POD类型的,那么就可以用memcpy函数快速构造,对于析构函数,可以什么都不做,直接标记空间不再使用即可。这样对于容器类可以大幅提升效率。 根据iterator_traits编写的经验,我们希望可以这样用__type__traits<T>,T代表任意类型。 __type__traits<T>::has_trivial_default_constructor;__type__traits<T>::has_trivial_default_destructor;__type__traits<T>::has_trivial_copy_constructor;__type__traits<T>::has_trivial_assgnment_operator;__type__traits<T>::is_POD_type;我们希望上面的式子返回真或假,为了能激活函数重载,不再运行期影响效率,我们构建两个类来作为上式的返回值。 Struct __true__type{}; Struct __false__type{}; 为了完成上述式子,__type__traits内必须定义一些typedefs,SGI源码做法如下: struct __true_type {}; struct __false_type {}; template <typename type> struct __type_traits { typedef __true_type this_dummy_member_must_be_first;//和编译器相关 typedef __false_type has_trivial_default_constructor; typedef __false_type has_trivial_copy_constructor; typedef __false_type has_trivial_assignment_constructor; typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; //POD指的是这样一些数据类型:在内存布局中和C兼容的类型、 //构造函数是 trivial 的 struct 或者 class }; 所有自定义的类型,为了优化效率,也应该在类型内嵌这些声明。来使STL的算法通过__type__traits<T>::has_trivial_xxxx得知类型信息,进行效率优化。 SGI对于所有内置类型都给出了包含这些声明的特化版本。下面是源码: //type_traits.h #ifndefTYPE_TRAITS_H #defineTYPE_TRAITS_H struct__true_type {}; struct__false_type {}; template<typename type> struct__type_traits { //不要移除 typedef __true_typethis_dummy_member_must_be_first; //trivial指无意义的 typedef __false_typehas_trivial_default_constructor; typedef __false_typehas_trivial_copy_constructor; typedef __false_typehas_trivial_assignment_constructor; typedef __false_type has_trivial_destructor; typedef __false_type is_POD_type; //POD指的是这样一些数据类型:基本数据类型、指针、union、数组、 //构造函数是 trivial 的 struct 或者class }; //特化版本 template<> struct__type_traits<char> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<signed char> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<unsigned char> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<short> { typedef __true_typehas_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<unsigned short> { typedef __true_type has_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<int> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<unsigned int> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<long> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<unsigned long> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_type has_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<float> { typedef __true_typehas_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<double> { typedef __true_type has_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本 template<> struct__type_traits<long double> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; //特化版本(原生指针) template<class T> struct__type_traits<T*> { typedef __true_typehas_trivial_default_constructor; typedef __true_typehas_trivial_copy_constructor; typedef __true_typehas_trivial_assignment_constructor; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif 三.总结 1.Traits编程技法,通过与迭代器约定编写规范,成功的获取了对象的类型信息,从而使得算法可以通过类型信息来优化效率。 2.使用重载判断来去掉运行期冗余的if-else条件分支,再一次的提高了效率。通过结构体类型的相互继承,利用派生类与向基类指针的隐式转换,减少了算法的编写量。提高了效率。 3.通过对迭代器的traits扩展,使得所有类型都满足traits编程规范,这样STL算法可以通过type__traits获取类型信息后,进一步优化效率。 4.对于迭代器和原生指针获取对象类型信息的方法不统一的问题,通过增加一个间接层代理类来统一对外的方法和接口。成功运用代理模式解决了问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: