STL源码初步接触

STL = Standard Template Library,直译过来是:标准模板库,是惠普实验室开发的一系列软件的统称。从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用额外安装什么。STL所实现的,是依据泛型思维架设起来的一个概念结构。说了这么多还是不知道STL是个什么东东,今天只是初接触这个概念,感觉很高深的样子,先这样理解吧,STL就是一个仓库,一个存放各种工具的仓库。它的工具分为六大类(六大组件) :

容器(containers):各种数据结构,如Vector,list,deque,set,map,用来存放底层数据。一般有序列式(下面要写的Vector就是个这种)、关联式等。

算法(algorithms):各种常用算法如:sort,search,copy,erase……

迭代器(iterator):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共5种类型,以及他们的衍生变化。所有的STL容器都附带有自己专属的迭代器。原生指针也是一种迭代器。

仿函数(functor):行为类似函数可作为算法的某种策略。一般函数指针可认为是侠义的仿函数。

配接器(adapter):一种用来修饰容器,或仿函数,或迭代器接口的东西。

配置器(allocators)负责空间配置与管理。配置器是一个实现了动态空间配置、空间管理、空间释放的class template。

因为下面主要是实现Vector的简单操作,所以就再多讲一点它。Vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此Vector的运用对于内存的合理运用与运用得灵活性有很大的帮助。Vector维护的是一个连续的空间,无论元素的型别为何,普通指针都可以作为Vector的迭代器而满足所有必要条件。

Vector 的简单实现:

  1. #pragma once
  2. #include<iostream>
  3. #include<assert.h>
  4. #include<stdlib.h>
  5. using namespace std;
  6. template<class T>
  7. class Vector
  8. {
  9. public:
  10. typedef T* Iterator;
  11. typedef const T* Citerator;
  12. public:
  13. Vector()
  14. :start(NULL)
  15. ,finish(NULL)
  16. ,endofstorage(NULL)
  17. {}
  18. Vector(const Vector<T>& v)
  19. //:start(new T[v.endofstorage - v.start])
  20. //, finish(v.finish )
  21. //, endofstorage(v.endofstorage)
  22. :start(new T[v.endofstorage - v.start])
  23. , finish(start + (v.finish - v.start))
  24. ,endofstorage(start + (v.endofstorage - v.start)) {
  25. my_memcopy(start, v.start, sizeof(T)*(v.endofstorage - v.start));
  26. }
  27. //向Vector中存入size个元素
  28. Vector(Citerator array, size_t size)
  29. :start(new T[size])
  30. , finish(start)
  31. , endofstorage(start + size) {
  32. for (size_t index = ; index < size; ++size) {
  33. start[index] = array[index];
  34. finish++;
  35. }
  36. }
  37. Vector<T>&operator=(const Vector<T>& v) {
  38. if (this != &v) {
  39. Vector<int>tmp(v);
  40. swap(tmp);
  41. }
  42. return *this;
  43. }
  44. ~Vector(){
  45. if (start) {
  46. delete[] start;
  47. start = NULL;
  48. // delete[] finish;
  49. finish = NULL;
  50. // delete[] endofstorage;
  51. endofstorage = NULL;
  52. }
  53. }
  54. // 返回首元素的迭代器
  55. Iterator Begin() {
  56. return start;
  57. }
  58. Citerator Begin()const {
  59. return start;
  60. }
  61. // 获取Vector中最后一个元素的下一个位置
  62. Iterator End() {
  63. return finish:
  64. }
  65. Iterator End()const {
  66. return finish;
  67. }
  68. size_t Size()const {
  69. return finish - start;
  70. }
  71. size_t Capacity()const {
  72. return endofstorage - start;
  73. }
  74. bool Empty()const {
  75. return finish == start;
  76. }
  77. T& operator[](size_t index) {
  78. return start[index];
  79. }
  80. const T& operator[](size_t index)const {
  81. return start[index];
  82. }
  83. T& At(size_t index) {
  84. if ((index <= Size()) && (index >= ))
  85. return start[index];
  86. }
  87. const T& At(size_t index)const {
  88. if ((index <= Size()) && (index >= ))
  89. return start[index];
  90. }
  91. // 获取Vector中的第一个元素
  92. T& Front() {
  93. return srart[];
  94. }
  95. const T& Front()const {
  96. return start[];
  97. }
  98. // 获取Vector中的最后一个元素
  99. T& Back() {
  100. return start[finish - start];
  101. }
  102. const T& Back()const {
  103. return start[finish - start];
  104. }
  105. void PushBack(const T& x) {
  106. capacity();
  107. // start[finish - start + 1] = x;
  108. start[finish - start] = x;
  109. finish++;
  110. }
  111. void PopBack() {
  112. if (!Empty()) {
  113. finish--;
  114. }
  115. }
  116. // 在pos位置上插入元素x
  117. Iterator Insert(Iterator pos, const T& x) {
  118. for (size_t index = Size(); index >= (size_t)(pos - start); index--) {
  119. start[index + ] = start[index];
  120. }
  121. *pos = x;
  122. finish++;
  123. return pos;
  124. }
  125. // 删除pos位置上面的元素
  126. Iterator Erase(Iterator pos) {
  127. for (size_t index = (size_t)(pos - start); index < Size(); index++) {
  128. start[index] = start[index + ];
  129. }
  130. finish--;
  131. return pos;
  132. }
  133. // 给Vector赋值n个值为x的元素
  134. void Assign(size_t n, const T& x) {
  135. if (n > endofstorage - start) {
  136. finish = start + n;
  137. capacity();
  138. for (size_t index = ; index < n; index++) {
  139. start[index] = x;
  140. }
  141. }
  142. else {
  143. for (size_t index = ; index < n; index++)
  144. start[index] = x;
  145. }
  146. finish = start + n;
  147. }
  148. public:
  149. //自己管理 扩容
  150. void capacity() {
  151. if (finish >= endofstorage) {
  152. size_t capacity = * (endofstorage - start) + ;
  153. Iterator tmp = new T[capacity];
  154. // 拷贝元素
  155. my_memcopy(tmp, start, sizeof(T)*(endofstorage - start));
  156. size_t ret = finish-start;
  157. delete start;
  158. start = tmp;
  159. finish = start + ret;
  160. endofstorage = start + capacity;
  161. //
  162. /*Iterator pos = start;
  163. size_t index = 0;
  164. while (pos < endofstprage)
  165. temp[index++] = *pos++;
  166. deleta[] start;
  167. start = temp;
  168. finish = start + index;
  169. endofstorage = start + capacity;*/
  170.  
  171. }
  172. }
  173. void swap(Vector<T>& v) {
  174. std::swap(start, v.start);
  175. std::swap(finish, v.finish);
  176. std::swap(endofstorage, v.endofstorage);
  177. }
  178. void Print() {
  179. for (size_t i = ; i < Size(); i++)
  180. {
  181. cout << start[i] << " ";
  182. }
  183. cout << endl;
  184. }
  185. void* my_memcopy(void* dest, const void* src, size_t sz) {
  186. //assert(!dest || !src);
  187. assert(dest != NULL || src != NULL);
  188. char* ret = (char*)dest;
  189. char* tmp = (char*)src;
  190. while (sz--) {
  191. *ret = *tmp;
  192. ret++;
  193. tmp++;
  194. }
  195. return dest;
  196. }
  197. private:
  198. Iterator start;
  199. Iterator finish;
  200. Iterator endofstorage;
  201. };

其中,注释掉的代码部分是我曾经踩过的坑,下面是部分测试代码

  1. #include"vector.h"
  2. void Test1()
  3. {
  4. Vector<int> list1;
  5. list1.PushBack();
  6. list1.PushBack();
  7. list1.PushBack();
  8. list1.PushBack();
  9. list1.PushBack();
  10. list1.Print();
  11. Vector<int> list2;
  12. list2.PushBack();
  13. list2.PushBack();
  14. list2.PushBack();
  15. list2.PushBack();
  16. list2.PushBack();
  17. list2.Print();
  18. list1 = list2;
  19. list1.Print();
  20. }
  21. void Test2()
  22. {
  23. Vector<int> list1;
  24. list1.PushBack();
  25. list1.PushBack();
  26. list1.PushBack();
  27. list1.PushBack();
  28. list1.PushBack();
  29. list1.Print();
  30. list1.PopBack();
  31. list1.Print();
  32. list1.Insert(&list1.At(), );
  33. list1.Print();
  34. list1.Erase(&list1.At());
  35. list1.Print();
  36. }
  37. int main()
  38. {
  39. Test1();
  40. Test2();
  41. getchar();
  42. return ;
  43. }

注意:扩容时函数中my_memcpy()函数,它的本质就是值拷贝,当Vector中存放的内置类型时没有任何问题,但是像String类这种问题就无法解决。所以下面给出了另一种写法。

  1. /*Iterator pos = start;
  2. size_t index = 0;
  3. while (pos < endofstprage)
  4. temp[index++] = *pos++;
  5. deleta[] start;
  6. start = temp;
  7. finish = start + index;
  8. endofstorage = start + capacity;*/

C++模板--实现容器适配器的更多相关文章

  1. 8、泛型程序设计与c++标准模板库2.5容器适配器

    容器适配器是用来扩展7中基本容器的,是修改和调整其他类接口的类.他们不提供存放数据的实际数据结构的实现方法,而且容器适配器也不支持迭代器. 1.标准栈容器 使用STL中的标准栈为程序员提供了一层附加的 ...

  2. C++顺序性容器、关联性容器与容器适配器

    什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...

  3. C++ 容器:顺序性容器、关联式容器和容器适配器

    什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...

  4. 初步STL该容器适配器

    容器适配器 特点 容器一定的顺序来实现(让现有的以集装箱堆放/式工作) 分类 1) stack: 头文件 <stack> • 栈 -- 后进先出 2) queue: 头文件 <que ...

  5. 容器适配器————queue

    只能访问 queue<T> 容器适配器的第一个和最后一个元素.只能在容器的末尾添加新元素,只能从头部移除元素. 操作 queue<int> q;//创建一个int型的空队列q ...

  6. C++ Primer : 第九章 : vector变长、string的其他操作以及容器适配器

    vector变长机制.string的其他构造方法,添加.替换和搜索操作,string比较和数值转换,最后是容器适配器. vector对象是如何增长的 vector和string类型提供了一些成员函数, ...

  7. c++ 顺序容器学习 - 容器适配器

    摘要: 对 容器适配器 的疑问. 刚开始接触 容器适配器 时,总感觉怪怪的,认为多此一举,顺手搜了搜,原来我在这一点is not alone: STL容器适配器的用途 其中有个老兄说的好,这里 引用一 ...

  8. C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器

    STL实践与分析 --容器适配器 引: 除了顺序容器.标准库还提供了三种顺序容器适配器:queue,priority_queue和stack.适配器是标准库中的概念.包含容器适配器,迭代器适配器和函数 ...

  9. STL之容器适配器queue的实现框架

    说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是怎样借助基础容器实现一种经常使用的数据结构stack (栈),本文介绍下第二种STL ...

随机推荐

  1. PDO数据访问抽象层

    PDO数据访问抽象层: 我们使用的mysqli是针对mysql这个数据库扩展的一个类,如果要用到别的数据库的话就可以用PDO来做 1.操作数据库 先来代码 <!--PDO--> <! ...

  2. Python 3 读写文件的简单方法!

    Python 3 读写文件的简单方法! a = open('test.txt','w') 这行代码创建了一个名为test的文本文档,模式是写入(模式分为三种,w代表写入,r代表阅读,a代表在尾行添加) ...

  3. [HDUOJ1312]Red And Black (经典的DFS)

    Hot~~招聘——亚信科技,巴卡斯(杭州),壹晨仟阳(杭州),英雄互娱(杭州) (包括2016级新生)除了校赛,还有什么途径可以申请加入ACM校队? Red and Black Time Limit: ...

  4. JavaWeb与Asp.net工作原理比较分析

    一.概述 不管是什么语言开发的web应用程序,都是在解决一个问题,那就是用户输入url怎么把对应的页面响应出来,如何通过url映射到响应的类,由于自己做asp.net的时间也不短了,还算是对asp.n ...

  5. 使用Three.js网页引擎创建酷炫的3D效果的标签墙

    使用Three.js引擎(这是开源的webgl三维引擎,gitgub)进行一个简单应用. 做一个酷炫的3d效果的标签墙(已经放在我的博客首页,大屏幕可见), 去我的博客首页看看实际效果 www.son ...

  6. PHP-配置方法

    由于php是一个zip文件(非install版),安装较为简单,解压就行.把解压的 php5.2.1-Win32重命名为 php5.并复制到C盘目录下.即安装路径为 c:\php5 1 找到php目录 ...

  7. vue学习笔记(一)关于事件冒泡和键盘事件 以及与Angular的区别

    一.事件冒泡 方法一.使用event.cancelBubble = true来组织冒泡 <div @click="show2()"> <input type=&q ...

  8. C++数据

    const :常量 ~x == -++x == -(x+1)   二进制数,1变为0,0变为1 ^                               相同为0,不同为1 &      ...

  9. 单发邮箱 群发邮箱 程序 Email winform

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  10. 受限玻尔兹曼机(RBM)原理总结

    在前面我们讲到了深度学习的两类神经网络模型的原理,第一类是前向的神经网络,即DNN和CNN.第二类是有反馈的神经网络,即RNN和LSTM.今天我们就总结下深度学习里的第三类神经网络模型:玻尔兹曼机.主 ...