• 源代码之中时而会出现一些全局函数调用操作,尤其是定义于<stl_construct.h> 之中用于对象构造与析构的基本函数,以及定义于<stl_uninitialized.h>之 中 用 于 内 存 管 理 的 基 本 函 数 , 以及定义于<stl_algobase.h>之中的各种基本算法

STL六大组件功能与运用

  • 容 器 (containers) : 各种数据结构,如  vector, list , deque, set, map,用来存放数据,详见本书4, 5 两章。从实现的角度来看,STL容器是一种class template.就体积而言,这一部分很像冰山在海面下的比率
  • 算 法 (algorithm s): 各种常用算法如 sort, search, copy, erase - - 详见 第 6 章。从实现的角度来看,STL算法是一种function template.
  • 迭代器(iterators): 扮演容器与算法之间的胶合剂,是所谓的“泛型指针”, 详见第3 章.共有五种类型,以及其它衍生变化.从实现的角度来看,迭代器是一种将 operator*, operator->, operator++, operator--等指针相关操作予以重载的class template.所有STL容器都附带有自己专属的迭代器—— 是的,只有容器设计者才知道如何遍历自己的元素。原生指针(native
    pointer)也是一种迭代器。
  • 仿函数(functors): 行为类似函数,可作为算法的某种策略(p olicy), 详见 第7章。从实现的角度来看,仿函数是一种重载了 operator ()的class或 class template. 一般函数指针可视为狭义的仿函数。
  • 配 接 器 (adapters): —种用来修饰容器(containers)或仿函数(functors)或迭代器(iterators)接口的东西,详见第8 章• 例如,STL提供的queue和 stack,虽然看似容器,其实只能算是一种容器配接器,因为它们的底部完全 借助deque,所有操作都由底层的deque供应。改变functor接口者,称为function adapter;改变 container 接口者,称为 container adapter;改变 iterator
    接口者,称 为 iterator adapter.配接器的实现技术很难一言以蔽之,必须逐 —分析,详见第8章
  • 配置器(allocators): 负责空间配置与管理,详见第2 章。从实现的角度来 看,配置器是一个实现了动态空间配置、空间管理、空间释放的class template.

1.8.3 SGI STL 的 编 译 器 组 态 设 置 ( configuration )

  • 不同的编译器对C++语言的支持程度不尽相同。作为一个希望具备广泛移植能力的程序库,SGI S T L 准备了一个环境组态文件<stl_config.h>,其中定义了许多常量,标示某些组态的成立与否。所有STL头文件都会直接或间接包含这个组态文件,并以条件式写法,让预处理器(pre-processor)根据各个常量决定取舍哪 一段程序代码。例如:

  • <stl_Config.h>文件起始处有一份常量定义说明,然后即针对各家不同的编 译器以及可能的不同版本,给予常量设定。从这里我们可以一窥各家编译器对标准C++的支持程度。
  • 所谓临时对象,就是一种无名对象(unnamed objects) >,它的出现如果不在程 序员的预期之下(例如任何pass by value操作都会引发copy操作,于是形成一 个临时对象),往往造成效率上的负担。但有时候刻意制造一些临时对象,却又是使程序干净清爽的技巧。
  • 刻意制造临时对象的方法是,在型别名称之后直接加一对小括号,并可指定初值,例 如 Shape (3,5)或 int(8),其意义相当于调用相应 的constructor且不指定对象名称。
  • STL 最常将此技巧应用于仿函数(functor)与 算法的搭配上,例如:
  • 最后一行便是产生function template具现体print<int>的一个临时对象。 这个对象将被传入for_each()之中起作用。当 for_each()结束时,这个临时对 象也就结束了它的生命。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <functional>
#include <deque>template <typename T>
class print{
public:void operator() (const T& elem) {//operator() 重载std::cout << elem << std::endl;}
};
int main(int argc,char* argv[]){int ia[6] = {0,1,2,3,4,5};std::vector<int>iv(ia,ia+6);std::for_each(iv.begin(),iv.end(), print<int>());
}
  • 静态常量整数成员在c la ss内部直接初始化 in-class static constant integer initialization
  • 如 果 class内含 const static integral data m e m b e r , 那么根据 C + + 标准规格,
    我们可以在class之内直接给予初值。所 谓 integral泛指所有整数型别,不单只是 指 int。下面是一个例子:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <functional>
#include <deque>template <typename T>
class print{
public:void operator() (const T& elem) {//operator() 重载std::cout << elem << std::endl;}
};template <typename T>
class testClass{
public:static const int _datai = 5;static const long _datal = 3L;static const char _datac = 'c';
};
int main(int argc,char* argv[]){std::cout << testClass<int>::_datai << std::endl;std::cout << testClass<int>::_datal << std::endl;std::cout << testClass<int>::_datac << std::endl;
}
  • increm ent/decrem ent/dereference 操作符
  • increment/dereference操作符在迭代器的实现上占有非常重要的地位,因为 任何~个迭代器都必须实现出前进(讥er e * ” 和取值(dereference, operator*) 功能,前者还分为前置式(prefix)和后置式(postfix)两种,有非常 规律的写法14°有些迭代器具备双向移动功能,那么就必须再提供decrement操作 符 (也分前置式和后置式两种)。下面是一个范例:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <vector>
#include <functional>
#include <deque>template <typename T>
class print{
public:void operator() (const T& elem) {//operator() 重载std::cout << elem << std::endl;}
};template <typename T>
class testClass{
public:static const int _datai = 5;static const long _datal = 3L;static const char _datac = 'c';
};class INT{friend std::ostream& operator<<(std::ostream & os,const INT& i);
public:INT(int i) : m_i(i){};//prefix : increment and then fetchINT& operator++(){++(this->m_i); //随着class的不同,此行应该有不同的操作return *this;}//postfix : fetch and then incrementconst INT operator++(int){INT temp = *this;++(*this);return temp;}//postfix : decrement and then fetchINT& operator--(){--(this->m_i);return *this;}//postfix : fetch and then decrementconst INT operator--(int){INT temp = *this;--(*this);return temp;}//dereferenceint& operator*() const{return (int&)m_i;//以上转换操作告诉编译器,你确实要将const int转为non-const lvalue.//如果没有这样明白地转型,有些编译器会给你警告,有些更严格的编译器会视为错误}private:int m_i;
};std::ostream& operator<<(std::ostream&os,const INT& i){os << '[' << i.m_i << ']';return os;
}int main(int argc,char* argv[]){INT I(5);std::cout << I++;std::cout << ++I;std::cout << I--;std::cout << --I;std::cout << *I;
}
  • 前 闭 后 开 区 间 表 示 法 [)
  • 任何一个STL算法,都需要获得由一对迭代器(泛型指针)所标示的区间,用以表示操作范围。这一对迭代器所标示的是个所谓的前闭后开区间15,以 [first, last)表示。也就是说,整个实际范围从first开始,直到last-1.迭代器last 所指的是“最后一个元素的下一位置”。这种off by one (偏移一格,或说pass the end)的标示法,带来了许多方便,例如下面两个STL算法的循环设计,就显得干净利落:
  • 因为 以下两个函数都是递增遍历元素,所以使用 InputIterator
template <class InputIterator,class T>
InputIterator find(InputIterator first,InputIterator last,const T& value){while(first != last && *first!= value){return first;}
}template <class InputIterator,class Function>
Function for_each(InputIterator first,InputIterator last,Function f){for (; first != last;++first) {f(*first);}return f;
}

  • function call 操 作 符 ( o p e r a to r 。)
  • 很少有人注意到,函数调用操作(C ++语法中的左右小括号)也可以被重载
  • 许多STL算法都提供了两个版本,一个用于一般状况(例如排序时以递增方式排列),一个用于特殊状况(例如排序时由使用者指定以何种特殊关系进行排列)。像这种情况,需要用户指定某个条件或某个策略,而条件或策略的背后由一整组操作构成,便需要某种特殊的东西来代表这“一整组操作”
  • 代表“一整组操作”的,当然是函数• 过去C 语言时代,欲将函数当做参数传递 ,唯有通过函数指针(pointer to function,或 称 function pointer)才能达成,例如:

  • 但是函数指针有缺点,最重要的是它无法持有自己的状态(所谓局部状态,local states), 也无法达到组件技术中的可适配性(adaptability)—— 也就是无法再将某 些修饰条件加诸于其上而改变其状态。
  • 为此,S T L 算法的特殊版本所接受的所谓“条件”或 “策略”或 “一整组操作”,都以仿函数形式呈现。所谓仿函数(functor)就是使用起来像函数一样的东 西。如果你针对某个class进 行 operator()重载,它就成为一个仿函数。至于要 成为一个可配接的仿函数,还需要做一些额外的努力(详见第8 章 )。
  • 上 述 的 plus<T>和 minus<T>已经非常接近STL的实现了,唯一的差别在 于 它 缺 乏 “可配接能力”。关 于 “可配接能力
template <class T>
struct plus{T operator() (const T&x,const T&y) const{return x+y;}
};template <class T>
struct minus{T operator()(const T&x,const T&y) const{return x-y;}
};int main(int argc,char* argv[]){plus<int>plus_obj{};minus<int>minus_obj{};//以下使用仿函数,就像使用一般函数一样std::cout << plus_obj(3,5) << std::endl;std::cout << minus_obj(3,5) << std::endl;//以下直接产生仿函数的临时对象(第一对小括号),并调用之(第二对小括号)std::cout << plus<int>()(3,5) << std::endl;std::cout << minus<int>()(5,3) << std::endl;
}

请使用手机"扫一扫"x

STL源码剖析 入门开始 STL概论与版本简介相关推荐

  1. STL源码剖析-第一章STL概论与版本简介

    系列文章目录 第一章:STL概论与版本简介 文章目录 系列文章目录 前言 一.STL是什么? 二.STL六大组件 1.引入库 前言 源码之前 了无秘密 这本书不适合C++ 初学者,不适合 Generi ...

  2. 《STL源码剖析》学习--STL体现的思想

    STL总是尽量做到节省内存且效率最高,在看本书中也越来越有深的体会.这里搜集一个stl中提高效率的方法. 1.对象的复制.析构等 如果将一个区间中的所有的对象析构掉,这是如果范围很大,每个析构都是无关 ...

  3. stl源码剖析_《STL源码剖析》学习笔记——空间配置器

    目录 1. 空间配置器概述 2. 构造和析构基本工具 3. 空间的配置与释放,std::alloc 4. 内存基本处理工具 1. 空间配置器概述 从STL的实现角度来看,空间配置器的位置尤为重要,整个 ...

  4. stl源码剖析_《STL源码剖析》学习笔记

    第二章 空间配置器 简述空间配置器: 关于一级空间配置器: 直接使用malloc.free.realloc进行内存管理操作.且在内存不足时,会陷入oom_malloc,即模拟C++的set_new_h ...

  5. STL源码剖析(一):STL概论

    本系列是结合侯捷老师的 STL源码剖析这本书看的,有理解不到位的地方,敬请提出. 版本 首先,需了解以下三个C++编译器: GNU:Unix下的编译器 VC++:windows平台下的编译器,微软公司 ...

  6. STL源码剖析学习七:stack和queue

    STL源码剖析学习七:stack和queue stack是一种先进后出的数据结构,只有一个出口. 允许新增.删除.获取最顶端的元素,没有任何办法可以存取其他元素,不允许有遍历行为. 缺省情况下用deq ...

  7. 《STL源码剖析》学习-- 1.9-- 可能令你困惑的C++语法1

    最近在看侯捷的<STL源码剖析>,虽然感觉自己c++看得比较深一点,还是感觉还多东西不是那么明白,这里将一些细小的东西或者概念记录一下. 有些东西是根据<C++编程思想>理解的 ...

  8. 《STL源码剖析》学习--6章--_rotate算法分析

     最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. <STL源码剖析>学习--6章--random access ite ...

  9. 《STL源码剖析》学习--6章--power算法分析

    最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. 6章--power算法分析 书本中的算法如下所示: template <clas ...

最新文章

  1. Chrome开发,debug的使用方法。
  2. [android] 网络html查看器
  3. php7 安装zendopcache,安装PHP加速插件ZendOpcache
  4. asp.net学习笔记·文件上传
  5. apigee 安装_APIGEE – API网关简介
  6. 谷歌cloud_通过使用Google Cloud ML大规模提供机器学习模型,我们学到了什么
  7. php操作mysql数据库
  8. python 绘图 hist bin参数_Python-hist,distplot bin宽度不一致问题的解决方案
  9. jmeter5.1.1启动提示not able to find java executable or version的解决办法
  10. 2021年,UI行业真实前景到底如何?
  11. 组内Linq培训记录
  12. tomcat的安装以及配置
  13. 二进制和十进制之间的转换
  14. exchange网易企业邮箱服务器设置,网易企业邮箱Exchange协议邮件客户端配置指南...
  15. 印会河《中医基础理论》笔记——阴阳学说、五行学说
  16. UGUI优化:使用镜像图片
  17. jude(java建模软件)_JUDE(JAVA建模软件)
  18. 同花顺服务器文件夹,同花顺的文件目录.doc
  19. 对于“卡片复用”引来的一场尴尬。。。
  20. uvc camera MTK平台调试总结

热门文章

  1. nfc reader智能解码程序_更关注健康的高性价比智能手表 华米Amazfit Pop体验
  2. java反射机制详解_JAVA反射机制详解_JSP/Java编程_互联网开发技术网_传播最新的编程技术_php361.com...
  3. mysql not is null_转!!mysql 字段 is not null 和 字段 !=null
  4. 【转】C#检查键盘大小写锁定状态的方法
  5. 【转】C++学习四 冒泡排序法的一些改进
  6. 【转】VTK修炼之道2_VTK体系结构1
  7. 【转】TechEd第一课:新一代关系管理系统XRM**
  8. windows程序消息机制(Winform界面更新有关)
  9. .NET 实现并行的几种方式(二)
  10. 一步步编写操作系统 08 bios跳转到神奇的内存地址0x7c00