C++笔记七(STL与泛型编程)

标准库源代码在计算机中的分布

本机所用开发环境为visual studio 2013(包含了VC),其中C/C++所用的工具库包含在VC里面。


C++笔记七(STL与泛型编程)_第1张图片
标准库分布.png

C++笔记七(STL与泛型编程)_第2张图片
标准库 分布.png

OOP(面向对象编程)VS GP(泛型编程)

  • OOP企图将dates和methods关联在一起
    • list不能使用全局的sort()排序,因为全局sort()需要的是随机访问迭代器,例如first+(last-first)/2这样的只有RandomAccessIterator才能如此操作,而list因为内存模型的原因,不是连续空间,不能有iterator+5这种操作,所以它不能提供这种迭代器。
    • vector、deque等容器都提供RandomAccessIterator。
template
class list{
...
    void sort();
}
  • GP却是将datas和methods分开来,这样做的好处是:
    • Containers和Algorithms团队可各自闭门造车,其间以Iterator沟通即可。
    • Algorithms通过Iterators确定操作范围,并通过Iterators取用Container元素。
//Data Structures(Containers)
template
class vector{
...
};

//Alorithms
template
inline void
sort(_RandomAccessIterator _first,_RandomAccessIterator _last)
{
    ...
}
  • 所有algorithms,其内最终涉及元素本身的操作,无非就是比大小
bool strLonger(const string& s1,const string& s2) {return s1.size() < s2.size();}

cout<<"max of zoo and hello:"<     //函数1
inline const T& max(const T& a,const T& b){
  return a    //函数2
inline const T& max(const T& a,const T& b,Compare comp){
  return comp(a,b)?b:a;
}

分配器

  • operator new()追究到底最后调用的是C函数库中malloc()函数
  • VC6+、BC++、GCC2.9的allocator都只是以::operator new和::operator delete完成allocate()和deallocate(),没有任何特殊设计。
//VC6使用allocator,分配512ints
int* p=allocator().allocate(512,(int*)0);
allocator().deallocate(p,512);

//BC5使用allocator,分配512ints
int* p=allocator().allocate(512);
allocator().deallocate(p,512);

//G2.9使用allocator,分配512bytes
void* p=alloc::allocate(512);  //也可以alloc().allocate(512);
alloc::deallocate(p,512);
  • G2.9所附的标准库,其allocator实现如下:


    C++笔记七(STL与泛型编程)_第3张图片
    G2.9 allocator实现.png
  • 其中alloc的实现如下图():


    C++笔记七(STL与泛型编程)_第4张图片
    alloc实现.png
  • G4.9STL对allocator的使用:
template>
class vector :protected _Vector_base<_Tp , _Alloc>
{
   ...
}
  • G4.9所附的标准库,其allocator实现如下:


    C++笔记七(STL与泛型编程)_第5张图片
    G4.9 allocator实现.png

    C++笔记七(STL与泛型编程)_第6张图片
    G4.9 allocator实现.png
  • 相比G2.9,G4.9对于allocator的写法因为大量应用了类的继承、复合,使得观察者在理解allocator的实现上增加不少难度!

容器之间的实现关系与分类

  • 本图以缩排形式表达“基层与衍生层”的关系。这里所谓衍生,并非继承而是复合。
  • 在C++中,slist名为forward_list,hash_set,hash_map名为unordered_set,unordered_map,hash_multiset,hash_multimap名为unordered_multiset,unordered_multimap;且新添array。


    C++笔记七(STL与泛型编程)_第7张图片
    容器结构再分类.png

迭代器的设计原则和Iterator Traits的作用与设计

Iterators必须有能力回答algorithms的五个问题,也就是说Iterators必须提供五种associated types。


C++笔记七(STL与泛型编程)_第8张图片
Iterator需要遵循的原则.png

C++笔记七(STL与泛型编程)_第9张图片
五种associated types.png

为了分离class Iterators和non-class Iterators,就产生了Iterator traits,并且可以通过偏特化实现。


C++笔记七(STL与泛型编程)_第10张图片
Traits.png

C++笔记七(STL与泛型编程)_第11张图片
Traits 实现.png
  • 还有其他各式各样的traits
    • type traits ----------------<.../C++/type_traits>
    • iterator traits-------------<.../C++/bits/stl_iterator.h>
    • char traits----------------<.../C++/bits/char_traits.h>
    • allocator traits-----------<.../C++/bits/alloc_traits.h>
    • pointer traits-------------<.../C++/bits/ptr_traits.h>
    • array traits---------------<.../C++/bits/array>

深度探索list

参考链接【深度探索STL】详解 list
list 和vector 是两个最常用的容器(序列式容器)。二者最显著的区别自然就是vector是连续线性空间,list则是不连续线性空间,相比于vector(动态数组),它的好处是每次插入和删除一个元素,只需配置或释放一个元素空间,对于任何位置的元素插入或元素移除,list永远是常数时间。尺有所长,寸有所短,list 寻址某一元素也没有vector(常数时间)方便。

  • list 的迭代器
    • 因为链表节点在储存空间中不一定是连续存在的,自然也就不能像vector一样用普通指针作为迭代器。list迭代器必须有能力指向list的节点,并有能力正确的递增。递减。取值、成员存取等操作。这是作为任何一个容器的迭代器必须具备的。对于非连续空间的递增,递减等操作自然是针对该容器的属性来的,就list而言,则是指向上一个节点,下一个节点,以及获取指定节点。
      STL list是一个双向链表,迭代器必须具备前移,后移的能力,所以list提供的是bidirectional iterator (双向一个个移动)。关于迭代器的分类,参见STL迭代器。vector是随机迭代器类型(random access iterator),这也是符合vector 可随机存取的能力。
struct _List_iterator_base {  
    typedef size_t                     size_type;  
    typedef ptrdiff_t                  difference_type;  
    typedef bidirectional_iterator_tag iterator_category;  
  
    _List_node_base* _M_node;  
  
    //构造函数  
    _List_iterator_base(_List_node_base* __x) : _M_node(__x) {}  
    _List_iterator_base() {}  
  
    //增加和减少,就是指向上一个节点和下一个节点  
    void _M_incr() { _M_node = _M_node->_M_next; }  
    void _M_decr() { _M_node = _M_node->_M_prev; }  
  
    //运算符重载  
    bool operator==(const _List_iterator_base& __x) const {  
        return _M_node == __x._M_node;  
    }  
    bool operator!=(const _List_iterator_base& __x) const {  
        return _M_node != __x._M_node;  
    }  
};  
  
template  
struct _List_iterator : public _List_iterator_base {  
    typedef _List_iterator<_Tp, _Tp&, _Tp*>             iterator;  
    typedef _List_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;  
    typedef _List_iterator<_Tp, _Ref, _Ptr>             _Self;  
  
    typedef _Tp value_type;  
    typedef _Ptr pointer;  
    typedef _Ref reference;  
    typedef _List_node<_Tp> _Node;  
  
    //下面是子类指针赋值给父类指针,is-a原则(反过来不行)  
    _List_iterator(_Node* __x) : _List_iterator_base(__x) {}  
    _List_iterator() {}  
    _List_iterator(const iterator& __x) : _List_iterator_base(__x._M_node) {}  
  
    //对迭代器取值,获取节点的数据  
    reference operator*() const { return ((_Node*)_M_node)->_M_data; }  
  
    //对迭代器的成员存取,返回的是地址  
#ifndef __SGI_STL_NO_ARROW_OPERATOR  
    pointer operator->() const { return &(operator*()); }  
#endif /* __SGI_STL_NO_ARROW_OPERATOR */  
  
    //前缀和后缀++和--自增自减符重载  
    _Self& operator++() {  
        this->_M_incr();  
        return *this;//返回引用,可链式操作  
    }  
    _Self operator++(int) {  
        _Self __tmp = *this;  
        this->_M_incr();  
        return __tmp;//返回变量,不可链式操作  
    }  
    _Self& operator--() {  
        this->_M_decr();  
        return *this;  
    }  
    _Self operator--(int) {  
        _Self __tmp = *this;  
        this->_M_decr();  
        return __tmp;  
    }  
};  
C++笔记七(STL与泛型编程)_第12张图片
list iterator.png

C++笔记七(STL与泛型编程)_第13张图片
list iterator.png

深度探索vector

vector 将其元素置于一个动态数组中加以管理,与 array 非常类似,两者的唯一差别在于空间运用的灵活性,array 是静态空间,一旦配置了就不能更改,当需要容纳更多的元素时(此时已越界),需要重新手动配置更大的 array 空间,然后重新置入数据。而 vector 是动态空间,在同样的情况下,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。vector 同 array 一样可以很方便的通过索引值直接存取任何一个元素,在数组的尾端追加或移除元素均非常快速(当追加元素超出原有分配空间时,vector需要重新分配空间),但在其中间或头部插入移除元素就比较费时,需要移动安插点之后的所有元素以保持原来的相对位置。


C++笔记七(STL与泛型编程)_第14张图片
vector iterator.png

深度探索array&forward_list

与list和vector的iterator类似,有一种iterator traits用以分类class Iterators和non-class Iterators。


C++笔记七(STL与泛型编程)_第15张图片
array iterator.png

C++笔记七(STL与泛型编程)_第16张图片
forward_list iterator.png

你可能感兴趣的:(C++笔记七(STL与泛型编程))