C++ STL 体系结构与内核分析 P8-P15(list源码,迭代器设计原则)
C++ STL 体系结构与内核分析 P8-P15
- OOP(面向对象编程)和GP(泛型编程)
- 操作符重载
- 分配器allocators
- 容器之间的实现关系与分类
- 深度探索list(双向链表)
- 迭代器设计原则和Iterator Traits的作用与设计
分配器用于支撑容器对内存的使用
OOP(面向对象编程)和GP(泛型编程)
OOP企图把数据和操作放在一起
GP却是把数据和操作分开,操作容器时需要借用迭代器,好处是:
1)Container和Algorithm的团队可以各自闭门造车,以Iterator沟通
2)Algorithm通过Iterator确定操作范围,并通过Iterator取Container的元素
操作符重载
:: . .* :? 不能被重载(记忆方法:八个点)
** <> or &| 不能被重载
类模板:构造对象即实例化类的时候需要指定模板类型
函数模板:实参推导:定义函数模板,使用函数的时候直接传入参数,编译器可以自动识别函数参数类型从而决定函数返回类型或者调用相应的重载
成员模板:
类模板的泛化和特化及偏特化:
泛化:普通的模板编程
template<class type>
struct _type_trains{......
}
特化:模板类绑定了某种类型,比如int或double,此时语法为template<>,<>中为空
template<>
struct _type_trains<int>{......
}
偏特化(<>内参数个数偏特化):vector本来可以接受任意的类型作为元素,但是如果此时指定元素类型为bool,则stl利用偏特化构造一个特别的设计,这样可以使得针对boo元素类型的vector效率高或者空间小
//泛化
template<class Tclass Alloc=alloc>
class vector{......
};
//偏特化
template<class Alloc>
class vector<bool,Alloc>
{...
};
偏特化(<>内参数范围偏特化):模板类型为T,当传入T类的指针时,构造相对应的类
template<class T>
struct iterator_train<T*>{.......
}
或者
template<class T>
struct iterator_train<const T*>{.......
}
分配器allocators
VC6中allocators()分配内存时调用::operator new(),归根结底是调动malloc();撤销内存时调用::operator delete,归根到底是调用free()
malloc()分配内存时,除了所需要的内存空间之外害需要附加定量的额外空间,如果所需要malloc分配的内存越大,则额外空间占比越小
allocators直接使用的示例,模板后直接加小括号()生成临时对象,没有名称,因为撤销内存时也需要指定定义的内存大小而太过麻烦,所以不直接使用allocator
int *p=allocator<int>().allocate(512,(int*)0)//分配512个整型的内存
allocator<512>().deallocate(p,512);
在G4.9版本的C++中,比较好的分配器为__pool_allco,用法如下:
vector<string,__gnu_cxx::__pool_alloc<string>>vec//__gnu_cxx为命名空间
容器之间的实现关系与分类
深度探索list(双向链表)
1.任一容器源码内都包括了将iterator类,该类使得迭代器成为一个智能指针,iterator类中包括了对操作符++,–,&,->的重载
2.前置运算符++i的重载中返回对象本身的引用,是一个左值,所以可以有++++i的操作;后置运算符i++的重载中调用了前置运算符++i的重载,返回一个新对象为初始对象的副本,是一个右值,故不可以i++++操作
3.链表的实现是环状的双向环状链表中刻意在尾端加入空白结点,以实现容器前闭后开区间特性,
4.list不支持下标访问,但是插入和删除元素的时间复杂度都是O(1)
4.list的内存空间决定于成员数据而跟成员函数无关,这个原则适合其他所有类。指针成员数据类型占win位/8字节,如果编写为64代码(为64位系统),则指针类大小为64/8=8字节。如果类中存在虚函数,无论多少个虚函数,需要另外增加win位/8字节
5.advance的作用是将迭代器移动到需要的位置,再进行删除或者插入方法适用于各种容器
G2.9版本list源码
//G2.9版本list源码
//list 类
template <class T,class Alloc=alloc>
class list{protected:typedef __list_node<T> list_node;
public:typedef list node* link type;typedef __list_iterator<T,T&,T*>iterator;
protected:link_type node;
...
}
//结点类,包括了指向前后结点的指针和一个数据,指针类型在后续版本中被修改为初始化为指向自己本身结点类的对象
template <class T>
struct __list_node{typedef void* void pointer;void_point prev;void_point next;T data;
}
//迭代器类
template<class T,class Ref,class Ptr>
struct __list_iterator{//五个问题即五种属性typedef bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Ptr pointer;typedef Ref reference;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;}
}
List使用
list<int> lst; // 定义一个int类型的列表a
list<int> lst(10);// 定义一个int类型的列表a,并设置初始大小为10
list<int> lst(10, 1); // 定义一个int类型的列表a,并设置初始大小为10且初始值都为1
int n[] = { 1, 2, 3, 4, 5 };
list<int> a(n, n + 5); // 将数组n的前5个元素作为列表a的初值
// 头部增加元素
lst.push_front(4);
// 末尾添加元素
lst.push_back(5);
// 任意位置插入一个元素,begin函数会产生一个迭代器start,指向链表开头,使用advance将迭代器移到需要的位置,再插入
list<int>::iterator it = lst.begin();
advance(it,2)
lst.insert(it, 2);
// 任意位置插入n个相同元素,插入3个9
lst.insert(lst.begin(), 3, 9);
迭代器设计原则和Iterator Traits的作用与设计
Iterator需要遵循的原则:
算法“提出问题”,Iterator“回答问题”,相当于算法需要知道Iterator的五个属性(associated types):
1)iterator_categoty():迭代器分类,具体是指跨度,比如c+=3,c+=5等
2)difference_type():两个迭代器之间的距离应该用什么类型来表示
3)value_type():迭代的元素的类型
4)和5)分别为reference和pointer,这两种在标准库中未出现
Iterator Traits用于分离calss iterators和non-class iterators
calss iterators:list,vector等基于类,构造的时候需要告知模板参数类型所以可以直接获取associated types
non-class iterators:指针类,
C++ STL 体系结构与内核分析 P8-P15(list源码,迭代器设计原则)相关推荐
- STL体系结构与内核分析-2-STL体系结构基础介绍(侯捷)--笔记
STL体系结构与内核分析(侯捷) 2.STL体系结构基础介绍 STL设计方式与OO(面向对象)不同的地方,OO鼓励数据和处理数据的方法都放在类里,而STL的数据在容器里,操作数据的方法在其他部件里(模 ...
- [侯捷]C++ STL 体系结构与内核分析--从平地到万丈高楼(数据结构)
01认识headers.版本.重要资源 泛型编程:即使用Template,而STL就是使用了泛型编程 重要资源,编程能用到reference 另一个网站,将STD的内容已经分为了六大类 另一个 p2 ...
- linux内核线程socket,从Linux源码看Socket(TCP)的accept
从Linux源码看Socket(TCP)的accept 前言 笔者一直以为若是能知道从应用到框架再到操做系统的每一处代码,是一件Exciting的事情. 今天笔者就从Linux源码的角度看下Serve ...
- 对标阿里P8的MyBatis源码解析文档,面试/涨薪两不误,已献出膝盖
移动互联网的特点是大数据.高并发,对服务器往往要求分布式.高性能.高灵活等,而传统模式的Java数据库编程框架已经不再适用了. 在这样的背景下,一个Java的持久框架MyBatis走入了我们的世界,它 ...
- 【Linux 内核】进程管理 ( 内核线程概念 | 内核线程、普通进程、用户线程 | 内核线程与普通进程区别 | 内核线程主要用途 | 内核线程创建函数 kernel_thread 源码 )
文章目录 一.内核线程概念 二.内核线程.普通进程.用户线程 三.内核线程.普通进程区别 四.内核线程主要用途 五.内核线程创建函数 kernel_thread 源码 一.内核线程概念 直接 由 Li ...
- 【Android 事件分发】ItemTouchHelper 源码分析 ( OnItemTouchListener 事件监听器源码分析 二 )
Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...
- 【Android 事件分发】ItemTouchHelper 源码分析 ( OnItemTouchListener 事件监听器源码分析 )
Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...
- 【OkHttp】OkHttp 源码分析 ( OkHttpClient.Builder 构造器源码分析 )
OkHttp 系列文章目录 [OkHttp]OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 ) [OkHttp]Android 项目导入 OkHttp ( 配置依赖 | 配置 ...
- Flume 1.7 源码分析(一)源码编译
Flume 1.7 源码分析(一)源码编译 Flume 1.7 源码分析(二)整体架构 Flume 1.7 源码分析(三)程序入口 1 说明 Flume是Cloudera提供的一个高可用的,高可靠的, ...
最新文章
- python staticmethod and classmethod方法
- Flutter开发之Android应用打包发布(22)
- Jobs(三) HTML的form表单提交中文后,后台取出乱码的问题
- 【DP、线段树优化】琪露诺
- 干货 | 机器学习入门方法和资料合集
- 剑指offer之3-10题解
- python内置作用域_python内置金融数据Python 五点搞定作用域
- JVM系列之内存泄漏
- python elasticsearch查询_python 查询Elasticsearch的小例子
- 同步设备IO与异步设备IO
- 英特尔回应安全漏洞问题:已在硬件层面解决
- 产品经理之深度学习促进产品之分类(三)
- 2011年1月28日早会资料(最终版本)
- [转载] python无法从nltk中调取文本 from nltk.book import *
- 6. jQuery 效果 - 淡入淡出
- POJ 2478:Farey Sequence
- c# 操作FTP文件类
- 高斯混合模型及python代码
- kewail node 短信_node.js短信接口_node.js发短信_node.js短信验证码_验证码短信代码示例_互亿无线...
- 01 #pragma once用法总结