STL分析(一)泛型编程,测试容器

六大部件

在这里插入图片描述
迭代器iterator是一种泛化指针,Adapter用于做转换,仿函数用于实现加减等简单的功能。
六大部件使用例子

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>
 
using namespace std;
 
int main()
{
    int ia[6] = {1, 2, 3, 4, 5, 6};
    vector<int, allocator<int>> vi(ia, ia + 6);
 
    cout << count_if(vi.begin(), vi.end(),
                not1(bind2nd(less<int>(), 3)));
    //not1是一个function adapter(negator)
    //bind2nd是一个function adapter(binder)
    //less<int>()是一个function object(是个临时对象)
    
    return 0;
}

c.begin()和c.end()传回的是iterator对象,即元素指针。分别指向第一个元素和最后一个元素的下一个元素,元素区间为前闭后开,可以使用*(c.begin()),但不能用 *(c.end())。
请添加图片描述
调用方式:

Container<T> c;
...
Container<T>::iterator ite = c.begin();
for(; ite != c.end(); ++ite)
	...

C++11后

std::vector<douuble> vec;
...
for (auto elem: vec) {
	std::cout<<elem<<std::endl;
}

for (auto& elem : vec) {
	elem *= 3;
}
//initializer_list
for ( int i : {1, 2, 3, 4}){
	std::cout << i << std::endl;
}

容器分类与测试

在这里插入图片描述
大致分为两类:序列型容器和关联型容器,标红的是C++11后出现的新容器

测试序列式容器

测试的辅助函数
在这里插入图片描述
定义两个target输入函数辅助容器的find函数查找元素,定义两个比较准则来比较容器元素。
(1)array
在这里插入图片描述
(2)vector
在这里插入图片描述
在这里插入图片描述

  • push_back()了一百万个元素,vector用了3000ms,和array比起来慢了很多,原因是vector需要二倍成长扩容。vector每次二倍成长时都要开辟新的空间,将原来的vector拷贝到新的空间内,而array的空间是静态分配的。
  • vector使用::find几乎不耗时,反而是二分查找时间较长,运气比较好

(3)list
在这里插入图片描述
(4)forward_list
在这里插入图片描述
单链表没有size()和back()的成员函数
(5)deque

deque的两端扩容

对比vector的扩容是在一个地方开辟足够的空间,然后把原来的地方的元素copy过去,因为原地扩容的话可能地方会不够用,而deque不是采用这种方式扩容。
在这里插入图片描述
deque是由一段段buffer组成的,每段buffer有固定的长度,deque维护指向每个buffer的指针,当deque需要扩容时,就在前面或后面新增一个buffer。因此实质上deque是分段连续的,但在deque源码中通过重载迭代器的相关操作使其表现为整段连续。

deque测试情况
在这里插入图片描述
容器适配器stack和queue内部就是一个deque,从而实现栈和普通队列的行为

测试关联容器

(1)multiset
在这里插入图片描述
容器本身的find()比全局的find()快很多,这是因为multiset内部采用红黑树结构实现,查找速度为log2n
(2)multimap
在这里插入图片描述
插入时用pair<>将两个key和value元素配对后再插入,multimap不能用c[ key ] = value 即用[ ]做插入。其内部也采用红黑树实现,可进行元素的快速查找。
(3)unordered_multiset
在这里插入图片描述

其中有一个bucket_count()的成员函数,可以看见篮子的数量,内部采用hashtable实现

(4)unordered_multimap
在这里插入图片描述

同样不可以采用[ ]做插入
(5)set,map,unorded_set,unordered_map
实现和上面大同小异,但要注意的一点是map和unordered_map可以用[ ]做插入,即

snprintf(buf, 10, "%d", rand());
c[i] = string(buf);

OOP和GP

  • GP将datas和method分开来
  • OOP将datas和method关联到一起

在list中体现了OOP,list不能使用全局的::sort()函数
在这里插入图片描述

我们发现::sort()支持的迭代器是随机访问迭代器,随机访问迭代器除了可以递增递减之外,还支持类似c.begin() + k的操作,而list中的迭代器不是随机访问迭代器,所以也就不提供这个操作。这样设计是合理的,因为list是链表,无法在线性时间内得到递增或递减k次的结果。
在这里插入图片描述
在其他容器如vector和deque中,可以调用全局的sort函数进行排序,其中_Compare _compare为仿函数对象,用于比较元素大小,定义如下:
在这里插入图片描述
图中调用了strLonger仿函数的比较准则来进行元素大小的比较,返回一个bool值

采用GP优势

  • Container和Algorithms可以各自闭门造成,用iterator沟通即可
  • Algorithms通过Iterators确定范围,并通过Itertors确定操作范围,并通过Iterators操作Container元素

操作符重载

在这里插入图片描述
有些操作符重载既可以是成员函数也可以使全局函数,有些操作符重载只能是成员函数

例子

template <class T, class Ref, class Ptr>
struct __list_iterator{
    typedef __list_iterator<T, Ref, Ptr>     self;
    typedef bidirectional_iterator_tag       iterator_catagory;
    typedef T                                value_type;
    typedef Ptr                              pointer;
    typedef Ref                              reference;
    typedef __list_node<T>*                  link_type;
    typedef ptrdiff_t                        difference_type;
 
    link_type node;
 
    reference operator*() const { return (*node).data; }
    pointer operator->()  const { return &(operator*()); }
    self& operator++()          { node = (link_type)((*node).next); return *this; }
    self operator++(int)        { self tmp = *this; ++*this; return tmp; }
};

模板

偏特化模板

(1)个数上偏

//泛化
template <class T,
          class Alloc = alloc>
class vector
{
    ......
};
 
//个数上的偏特化
template <class Alloc>
class vector<bool, Alloc>
{
    ......
};

范围上偏

//泛化
template <class Iterator>
struct iterator_traits{
    typedef typename Iterator::iterator_catagory    iterator_catagory;
    typedef typename Iterator::value_type           value_type;
    typedef typename Iterator::difference_type      difference_type;
    typedef typename Iterator::pointer              pointer;
    typedef typename Iterator::reference            reference;
};
 
 
//partial specialization for regular pointers
template <class T>
struct iterator_traits<T*>{
    typedef random_access_iterator_tag    iterator_catagory;
    typedef T                             value_type;
    typedef ptrdiff_t                     difference_type;
    typedef T*                            pointer;
    typedef T&                            reference;
};
 
//partial specialization for regular const pointers
template <class T>
struct iterator_traits<const T*>{
    typedef random_access_iterator_tag    iterator_catagory;
    typedef T                             value_type;
    typedef ptrdiff_t                     difference_type;
    typedef T*                            pointer;
    typedef T&                            reference;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值