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 = 0; index < size; ++size) {
33 start[index] = array[index];
finish++;
34 }
35 }
36 Vector<T>&operator=(const Vector<T>& v) {
37 if (this != &v) {
38 Vector<int>tmp(v);
39 swap(tmp);
40 }
41 return *this;
42 }
43 ~Vector(){
44 if (start) {
45 delete[] start;
46 start = NULL;
47 // delete[] finish;
48 finish = NULL;
49 // delete[] endofstorage;
50 endofstorage = NULL;
51 }
52 }
53 // 返回首元素的迭代器
54 Iterator Begin() {
55 return start;
56 }
57 Citerator Begin()const {
58 return start;
59 }
60 // 获取Vector中最后一个元素的下一个位置
61 Iterator End() {
62 return finish:
63 }
64 Iterator End()const {
65 return finish;
66 }
67 size_t Size()const {
68 return finish - start;
69 }
70 size_t Capacity()const {
71 return endofstorage - start;
72 }
73 bool Empty()const {
74 return finish == start;
75 }
76 T& operator[](size_t index) {
77 return start[index];
78 }
79 const T& operator[](size_t index)const {
80 return start[index];
81 }
82 T& At(size_t index) {
83 if ((index <= Size()) && (index >= 0))
84 return start[index];
85 }
86 const T& At(size_t index)const {
87 if ((index <= Size()) && (index >= 0))
88 return start[index];
89 }
90 // 获取Vector中的第一个元素
91 T& Front() {
92 return srart[0];
93 }
94 const T& Front()const {
95 return start[0];
96 }
97 // 获取Vector中的最后一个元素
98 T& Back() {
99 return start[finish - start];
100 }
101 const T& Back()const {
102 return start[finish - start];
103 }
104 void PushBack(const T& x) {
105 capacity();
106 // start[finish - start + 1] = x;
107 start[finish - start] = x;
108 finish++;
109 }
110 void PopBack() {
111 if (!Empty()) {
112 finish--;
113 }
114 }
115 // 在pos位置上插入元素x
116 Iterator Insert(Iterator pos, const T& x) {
117 for (size_t index = Size(); index >= (size_t)(pos - start); index--) {
118 start[index + 1] = start[index];
119 }
120 *pos = x;
121 finish++;
122 return pos;
123 }
124 // 删除pos位置上面的元素
125 Iterator Erase(Iterator pos) {
126 for (size_t index = (size_t)(pos - start); index < Size(); index++) {
127 start[index] = start[index + 1];
128 }
129 finish--;
130 return pos;
131 }
132 // 给Vector赋值n个值为x的元素
133 void Assign(size_t n, const T& x) {
134 if (n > endofstorage - start) {
135 finish = start + n;
136 capacity();
137 for (size_t index = 0; index < n; index++) {
138 start[index] = x;
139 }
140 }
141 else {
142 for (size_t index = 0; index < n; index++)
143 start[index] = x;
144 }
145 finish = start + n;
146 }
147 public:
//自己管理 扩容
148 void capacity() {
149 if (finish >= endofstorage) {
150 size_t capacity = 2 * (endofstorage - start) + 3;
151 Iterator tmp = new T[capacity];
// 拷贝元素
152 my_memcopy(tmp, start, sizeof(T)*(endofstorage - start));
154 size_t ret = finish-start;
155 delete start;
156 start = tmp;
157 finish = start + ret;
158 endofstorage = start + capacity;
//

/*Iterator pos = start;
size_t index = 0;
while (pos < endofstprage)
temp[index++] = *pos++;
deleta[] start;
start = temp;
finish = start + index;
endofstorage = start + capacity;*/

159         }
160 }
161 void swap(Vector<T>& v) {
162 std::swap(start, v.start);
163 std::swap(finish, v.finish);
164 std::swap(endofstorage, v.endofstorage);
165 }
166 void Print() {
167 for (size_t i = 0; i < Size(); i++)
168 {
169 cout << start[i] << " ";
170 }
171 cout << endl;
172 }
173 void* my_memcopy(void* dest, const void* src, size_t sz) {
174 //assert(!dest || !src);
175 assert(dest != NULL || src != NULL);
176 char* ret = (char*)dest;
177 char* tmp = (char*)src;
178 while (sz--) {
179 *ret = *tmp;
180 ret++;
181 tmp++;
182 }
183 return dest;
184 }
185 private:
186 Iterator start;
187 Iterator finish;
188 Iterator endofstorage;
189 };

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

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

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

/*Iterator pos = start;
size_t index = 0;
while (pos < endofstprage)
temp[index++] = *pos++;
deleta[] start;
start = temp;
finish = start + index;
endofstorage = start + capacity;*/

C++模板之Vector与STL初探的更多相关文章

  1. 模板类 vector

    概要 介绍一下模板类 vector 的常用操作,以及一个应用举例,顺时针打印矩阵.   基本定义 模板类 vector 是一种动态数组,它是使用 new 创建动态数组的替代品,实际上,vector 也 ...

  2. STL模板整理 vector

    一.什么是标准模板库(STL)? 1.C++标准模板库与C++标准库的关系 C++标准模板库其实属于C++标准库的一部分,C++标准模板库主要是定义了标准模板的定义与声明,而这些模板主要都是 类模板, ...

  3. 把《c++ primer》读薄(3-2 标准库vector容器+迭代器初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 标准库vector类型初探,同一种类型的对象的集合(类似数组),是一个类模版而不是数据类型,学名容器,负责管理 和 存储的元素 ...

  4. 对vector等STL标准容器的排序操作

    [+] STL提供的Sort 算法 所有sort算法介绍 sort 中的比较函数 sort 的稳定性 全排序 局部排序 nth_element 指定元素排序 partition 和stable_par ...

  5. 对vector等STL标准容器进行排序操作(转!)

    西方有句谚语:不要重复发明轮子! STL几乎封装了所有的数据结构中的算法,从链表到队列,从向量到堆栈,对hash到二叉树,从搜索到排序,从增加到删除......可以说,如果你理解了STL,你会发现你已 ...

  6. C++ STL 初探

    学过C++的人肯定会很熟悉STL标准模板库,STL其实就是封装了一系列的接口,供我们调用.很多函数或者算法的实现不需要我们从头开始写,大大提高我们的编程效率.这篇博客在简单介绍STL的情况下,会详细的 ...

  7. C++ 标准模板库介绍(STL)

    1. STL 基本介绍 C++ STL(标准模板库)是惠普实验室开发的一系列软件的统称,是一套功能强大的 C++ 模板类.STL的目的是为了标准化组件,这样就不用重新开发,让后来者可以使用现成的组件, ...

  8. 智能指针类模板(上)——STL中的智能指针

    智能指针类模板智能指针本质上就是一个对象,它可以像原生指针那样来使用. 智能指针的意义-现代C++开发库中最重要的类模板之一-C++中自动内存管理的主要手段-能够在很大程度上避开内存相关的问题 1.内 ...

  9. 【转】c++中Vector等STL容器的自定义排序

    如果要自己定义STL容器的元素类最好满足STL容器对元素的要求    必须要求:     1.Copy构造函数     2.赋值=操作符     3.能够销毁对象的析构函数    另外:     1. ...

随机推荐

  1. MyBatis源码解析【2】构建项目

    有了之前的准备,今天就要开始构建学习使用的项目了.废话不多说.开始吧. 首先我用IDEA构建了一个空的maven项目,然后加入了Mybatis的依赖. <dependencies> < ...

  2. [图形学] Chp9 三维几何变换--栈处理函数与矩阵管理函数的区别

    矩阵管理函数:glLoadIdentity()是把当前活动矩阵设置为单位矩阵. 栈处理函数:glPushMatrix()是将当前活动的变换矩阵复制一份,压入栈顶:glPopMatrix()是破坏当前活 ...

  3. Spring中获取对象

    Spring是一个非常主流,而且是好用的框架.提供管理对象的容器,提供事务的支持,缓存,权限认证(往往不用).用来集成hibernate等.而管理对象的生命周期是其中一个非常重要的功能.在Spring ...

  4. href="#" 的坑

    第一次发博客, 也不讲究样式. 只是单纯的说一下踩过的坑,方便后人避坑吧 之前做项目的时候,碰到一个非常奇葩的问题. 就是在jqgrid中写了了一个简单的方法 {name:'已经存在的列名称', la ...

  5. eclipse 常用快捷键 及 windows快捷键

    Eclipse常用快捷键 打开Eclipse快捷键的快捷键 Ctrl+Shift+L 快捷键 描述 原英文描述 Ctrl+Shift+P 定位到光标所在处的括号的另一半括号的位置 Go to Matc ...

  6. 使用three.js加载3dmax资源,以及实现场景中的阴影效果

    使用three.js可以方便的让我们在网页中做出各种不同的3D效果.如果希望2D绘图内容,建议使用canvas来进行.但很多小伙伴不清楚到底如何为我们绘制和导入的图形添加阴影效果,更是不清楚到底如何导 ...

  7. Java 实现FTP上传和下载

    1. 目前网上开源的FTP Client主要有JFTP.FTP4.edtFtpjJ和Apache.FTPClient. 2. jftp地址:http://www.jmethods.com/ 3. ed ...

  8. DotNetCore跨平台~文章索引~永久更新

    本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...

  9. 用caffe一步一步实现人脸检测

    学习深度学习已有一段时间了,总想着拿它做点什么,今天终于完成了一个基于caffe的人脸检测,这篇博文将告诉你怎样通过caffe一步步实现人脸检测.本文主要参考唐宇迪老师的教程,在这里感谢老师的辛勤付出 ...

  10. (转)Linux服务器安装配置tomcat

    这里首先说明下,Linux下的Tomcat没有32位和64位的区分. tomcat是分windows版本与linux版本的,windows版本一般以exe或者zip格式:linux版本一般以tar.g ...