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. ubuntu主机名修改

    1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方法: 其一,打开一个GNOME终端窗口,在命令提示符中可以看到主机名,主机名通常位于"@"符号后: 其二,在终端窗口中输 ...

  2. Java 多态透析 详细理解

    1:什么是多态 一个对象的多种状态 (老师)(员工)(儿子) 教师 a =老钟; 员工 b =老钟; 2:多态体现 父类引用变量指向了子类的对象          Father f = new Son ...

  3. Merge使用

    Role r = new Role(); r.setName("TEST"); r.setDescription("123"); r.setLevel(2); ...

  4. Java+Tomcat + Idea + Jrebel 实现热部署

    1. 首先安装idea的jrebel插件, jrebel是收费的,所以要在网上下载验证码. 2. 安装好以后再setting 菜单能看到一个jrebel的菜单. 3.  4.其中需要选中frame失去 ...

  5. jsp注册页面验证,easyui的jsp+js表单验证

    1.1下面的代码是写在Js里面的,就直接写进去不用什么其他东西,这样一个表单验证就好了(1.2图) $.extend($.fn.validatebox.defaults.rules, { phone: ...

  6. 基于Jmeter和Jenkins搭建性能测试框架

    搭建这个性能测试框架是希望能够让每个人(开发人员.测试人员)都能快速的进行性能测试,而不需要关注性能测试环境搭建过程.因为,往往配置一个性能环境可能需要很长的时间. 1.性能测试流程 该性能测试框架工 ...

  7. 用Node.JS+MongoDB搭建个人博客(app.js接口文件)(二)

    app.js的GitHub地址:用力戳我然后点个star 说个题外话,THINKPHP是通过一个index.php来引入文件,所以被称为接口文件. 而NodeJS也有这样的接口文件,通常也会放在根目录 ...

  8. 导入 theano 失败。“cannot import name gof”

    按照网上教程安装好了 theano 之后,import theano 出现错误."cannot import name gof".网上找了很多教程,都不可行.最后找到如下教程.亲测 ...

  9. Result Maps collection does not contain value for...

    出现上述错误 主要是因为你的select标签内部的resultMap属性指向的不正确 在sql文件中只要有一个resultMap或resultType属性指向错误,则在这个文件中其余正确的语句也不能执 ...

  10. (转)ZXing生成二维码和带logo的二维码,模仿微信生成二维码效果

    场景:移动支付需要对二维码的生成与部署有所了解,掌握目前主流的二维码生成技术. 1 ZXing 生成二维码 首先说下,QRCode是日本人开发的,ZXing是google开发,barcode4j也是老 ...