C++标准库分析总结(一)——<标准库简介>

目录

1 你应该具备的基础

1.1 你应该具备的基础

1.2 我们的目标

2 标准库介绍

2.1 C++标准库与C++标准模板库二者关系及表现形式

2.2 STL六大部件

2.3 STL的简单使用

2.4 时间复杂度

2.5 STL中的区间表示法

3 标准库源代码版本介绍

3.1 VC的编译器源码目录

3.2 GNU C++的编译器源码目录

4 OOP(Object-Oriented programming)与GP(Generic Programming)

4.1 OOP(面向对象编程)企图将datas和methods关联在一起

4.2 GP(泛型编程)是将datas和methods分开来

5 阅读C++标准库源码的必要基础

5.1 操作符重载

5.2 模板

5.2.1 类模板:

5.2.2 函数模板:

5.2.3 成员模板:

5.2.4 模板特化(泛化与特化)

5.2.3 模板偏特化(特化与偏特化(局部特化 Partial Specialization))





1 你应该具备的基础

1.1 你应该具备的基础

  • C++基本语法(包括如何正确使用模板,templates)

1.2 我们的目标

  • 使用C++标椎库

  • 深入认识C++标准库(胸中自有丘壑)

  • 良好使用C++标准库

  • 扩充C++标准库

2 标准库介绍

  • C++标准库:C++ Standard Library

  • C++标准模板库:Standard Template Library(STL

2.1 C++标准库与C++标准模板库二者关系及表现形式

  • 标准库由编译器提供的(比如我们常见的VC,GCC...)STL 属于标准库的一部分(占比绝大部分85%左右),标准库一定是包含(大于)STL的

  • 标准库引用形式:

    • C++标准库都是以头文件的形式提供不带.h,比如:#include<vector>;

    • 新式C语言的头文件不带.h,一般是:#include<cstdio>;

    • 命令空间:namespace std;

                    

  • 标准库引用方法:
#include <iostream>
#include <cstdio>  //snprintf()
#include <cstdlib> //RAND_MAX
#include <cstring> //strlen(), memcpy()
#include <string>

using namespace std;
using std::cin;
using std::cout;
using std::string;

2.2 STL六大部件

STL六大部件解释如下:

  • 容器:容器就是我们存放数据的地方,相当于数据仓库,实现方式是类模板

  • 分配器管理容器背后的内存使用实现方式是类模板

  • 算法:常见的比如排序、查找等,实现方式是函数模板

  • 迭代器算法操作容器的桥梁,是一种泛化的指针,实现方式是类模板

  • 仿函数:或者叫Function Object(函数对象),它是一个类对象,其次它重载了()操作符使用在自定义类对象时,比如我们对石头进行排序,在算法操作时就可以写一些仿函数供算法正确使用,实现方式时类模板

  • 适配器相对于迭代器、仿函数、容器的数据转换,实现方式是类模板。statck和queue也被称为容器适配器。

2.3 STL的简单使用

 

#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(是个临时对象)
    //not1(bind2nd(less<int>(), 3)));是一个predicate(判断式)
    
    return 0;
}

2.4 时间复杂度

要讨论时间复杂度,其中n必须建立在足够大的工业数据基础上。

算法复杂度:大O表示法

       

2.5 STL中的区间表示法

   STL采用前闭后开区间表示数据的范围所有的数据都是通过begin()和end()两个函数表示数据的范围begin表示数据的头,end表示数据尾的下一个元素,也就是说,对end进行解引用操作得到的指针它是不确定的东西,也可能造成程序宕机或者其他不是你心里所想的东西。

3 标准库源代码版本介绍

3.1 VC的编译器源码目录

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include

3.2 GNU C++的编译器源码目录

4 OOP(Object-Oriented programming)与GP(Generic Programming)

  • OOP: Object-oriented programming 面向对象的编程例如C++中的类和对象

  • GP:Generic Programming 泛型编程例如C++中的模板

4.1 OOP(面向对象编程)企图将datas和methods关联在一起

比如标准库中的list:

template <class T,
          class Alloc = alloc>
class list{
......
    void sort();
};

我们看到list定义了一个自己的成员函数,那么为什么list不能使用::sort()进行排序呢,我们先来看一下::sort()的源码:

template <class RandomAccessIterator>
inline void sort(RandomAccessIterator first, RandomAccessIterator last){
    if(first != last){
        __introsort_loop(first, last, value_type(first), __lg(last - first) * 2);
        __final_insertion_sort(first, last);
    }
}
 
template <class RandomAccessIterator, class T, class Size>
void __introsort_loop(RandomAccessIterator first,
                      RandomAccessIterator last,
                      T*,
                      Size depth_limit){
......
    RandomAccessIterator cut = __unguarded_partition
        (first, last, T(__median(*first, *(first + (last - first)/2), *(last - 1))));
......
}

我们发现::sort()支持的迭代器是随机访问迭代器随机访问迭代器除了可以递增递减之外,还支持类似c.begin() + k的操作,而list中的迭代器不是随机访问迭代器,所以也就不提供这个操作。这样设计是合理的,因为list是链表,无法在线性时间内得到递增或递减k次的结果。

4.2 GP(泛型编程)是将datas和methods分开来

采用GP的好处:

(1)ContainersAlgorithms可以分别“闭门造车”,其间以iterator通信即可

(2)Algorithms通过iterators确定操作范围,并通过iterators取用Container的元素。

比如说vector和deque都提供随机访问迭代器所以可以使用::sort()进行排序,体现了GP的设计思想。

template <class T,
          class Alloc = alloc>
class vector{
......
};
 
 
template <class T,
          class Alloc = alloc,
          size_t BufSiz = 0>
class deque{
......
};

::sort()有两个版本:

template <typename _RandomAccessIterator>
inline void
sort(_RandomAccessIterator __first,
     _RandomAccessIterator __last)
{
    ......
}
 
 
template <typename _RandomAccessIterator,
          typename _Compare>
inline void
sort(_RandomAccessIterator __first,
     _RandomAccessIterator __last,
     _Compare __comp)
{
    ......
}

所有的算法,其内最终涉及元素本身的操作,无非就是比大小。

5 阅读C++标准库源码的必要基础

5.1 操作符重载

这张图总结得很好。注意操作符重载既可以是成员函数也可以是全局函数

但是不理解最后一栏,对象后面的一元操作符为啥非要有一个参数?(这个参数没有任何意义,只是为了区分前置和后置版本)

限制条件:哪些操作符不能重载

看一个例子:iterator是一个泛化的指针

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; }
    。。。
};

5.2 模板

5.2.1 类模板

5.2.2 函数模板

编译器对函数模板进行实参推导:

5.2.3 成员模板

5.2.4 模板特化(泛化与特化

  泛化(GP  Generic Programming),特化(Specialization),二者区别在于特化版本相比泛化版本可能存在效率上的优化

5.2.3 模板偏特化(特化与偏特化(局部特化 Partial Specialization)

  • 特化又叫做全部特化,上面的例子中类模板参数只有一个,其实可以由多个,这个全部特化就是对所有的参数都进行特殊绑定;

  • 偏特化叫做局部特化,下面例子对于多个参数只绑定其中一部分(局部数量或者局部范围内的绑定)。部分特化:个数上的偏特化+范围上的偏特化.

  

(1) 个数上的偏

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

(2) 范围上的偏

//泛化
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;
};

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值