C++模板--实现容器适配器
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 的简单实现:
- #pragma once
- #include<iostream>
- #include<assert.h>
- #include<stdlib.h>
- using namespace std;
- template<class T>
- class Vector
- {
- public:
- typedef T* Iterator;
- typedef const T* Citerator;
- public:
- Vector()
- :start(NULL)
- ,finish(NULL)
- ,endofstorage(NULL)
- {}
- Vector(const Vector<T>& v)
- //:start(new T[v.endofstorage - v.start])
- //, finish(v.finish )
- //, endofstorage(v.endofstorage)
- :start(new T[v.endofstorage - v.start])
- , finish(start + (v.finish - v.start))
- ,endofstorage(start + (v.endofstorage - v.start)) {
- my_memcopy(start, v.start, sizeof(T)*(v.endofstorage - v.start));
- }
- //向Vector中存入size个元素
- Vector(Citerator array, size_t size)
- :start(new T[size])
- , finish(start)
- , endofstorage(start + size) {
- for (size_t index = ; index < size; ++size) {
- start[index] = array[index];
- finish++;
- }
- }
- Vector<T>&operator=(const Vector<T>& v) {
- if (this != &v) {
- Vector<int>tmp(v);
- swap(tmp);
- }
- return *this;
- }
- ~Vector(){
- if (start) {
- delete[] start;
- start = NULL;
- // delete[] finish;
- finish = NULL;
- // delete[] endofstorage;
- endofstorage = NULL;
- }
- }
- // 返回首元素的迭代器
- Iterator Begin() {
- return start;
- }
- Citerator Begin()const {
- return start;
- }
- // 获取Vector中最后一个元素的下一个位置
- Iterator End() {
- return finish:
- }
- Iterator End()const {
- return finish;
- }
- size_t Size()const {
- return finish - start;
- }
- size_t Capacity()const {
- return endofstorage - start;
- }
- bool Empty()const {
- return finish == start;
- }
- T& operator[](size_t index) {
- return start[index];
- }
- const T& operator[](size_t index)const {
- return start[index];
- }
- T& At(size_t index) {
- if ((index <= Size()) && (index >= ))
- return start[index];
- }
- const T& At(size_t index)const {
- if ((index <= Size()) && (index >= ))
- return start[index];
- }
- // 获取Vector中的第一个元素
- T& Front() {
- return srart[];
- }
- const T& Front()const {
- return start[];
- }
- // 获取Vector中的最后一个元素
- T& Back() {
- return start[finish - start];
- }
- const T& Back()const {
- return start[finish - start];
- }
- void PushBack(const T& x) {
- capacity();
- // start[finish - start + 1] = x;
- start[finish - start] = x;
- finish++;
- }
- void PopBack() {
- if (!Empty()) {
- finish--;
- }
- }
- // 在pos位置上插入元素x
- Iterator Insert(Iterator pos, const T& x) {
- for (size_t index = Size(); index >= (size_t)(pos - start); index--) {
- start[index + ] = start[index];
- }
- *pos = x;
- finish++;
- return pos;
- }
- // 删除pos位置上面的元素
- Iterator Erase(Iterator pos) {
- for (size_t index = (size_t)(pos - start); index < Size(); index++) {
- start[index] = start[index + ];
- }
- finish--;
- return pos;
- }
- // 给Vector赋值n个值为x的元素
- void Assign(size_t n, const T& x) {
- if (n > endofstorage - start) {
- finish = start + n;
- capacity();
- for (size_t index = ; index < n; index++) {
- start[index] = x;
- }
- }
- else {
- for (size_t index = ; index < n; index++)
- start[index] = x;
- }
- finish = start + n;
- }
- public:
- //自己管理 扩容
- void capacity() {
- if (finish >= endofstorage) {
- size_t capacity = * (endofstorage - start) + ;
- Iterator tmp = new T[capacity];
- // 拷贝元素
- my_memcopy(tmp, start, sizeof(T)*(endofstorage - start));
- size_t ret = finish-start;
- delete start;
- start = tmp;
- finish = start + ret;
- 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;*/
- }
- }
- void swap(Vector<T>& v) {
- std::swap(start, v.start);
- std::swap(finish, v.finish);
- std::swap(endofstorage, v.endofstorage);
- }
- void Print() {
- for (size_t i = ; i < Size(); i++)
- {
- cout << start[i] << " ";
- }
- cout << endl;
- }
- void* my_memcopy(void* dest, const void* src, size_t sz) {
- //assert(!dest || !src);
- assert(dest != NULL || src != NULL);
- char* ret = (char*)dest;
- char* tmp = (char*)src;
- while (sz--) {
- *ret = *tmp;
- ret++;
- tmp++;
- }
- return dest;
- }
- private:
- Iterator start;
- Iterator finish;
- Iterator endofstorage;
- };
其中,注释掉的代码部分是我曾经踩过的坑,下面是部分测试代码
- #include"vector.h"
- void Test1()
- {
- Vector<int> list1;
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.Print();
- Vector<int> list2;
- list2.PushBack();
- list2.PushBack();
- list2.PushBack();
- list2.PushBack();
- list2.PushBack();
- list2.Print();
- list1 = list2;
- list1.Print();
- }
- void Test2()
- {
- Vector<int> list1;
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.PushBack();
- list1.Print();
- list1.PopBack();
- list1.Print();
- list1.Insert(&list1.At(), );
- list1.Print();
- list1.Erase(&list1.At());
- list1.Print();
- }
- int main()
- {
- Test1();
- Test2();
- getchar();
- return ;
- }
注意:扩容时函数中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++模板--实现容器适配器的更多相关文章
- 8、泛型程序设计与c++标准模板库2.5容器适配器
容器适配器是用来扩展7中基本容器的,是修改和调整其他类接口的类.他们不提供存放数据的实际数据结构的实现方法,而且容器适配器也不支持迭代器. 1.标准栈容器 使用STL中的标准栈为程序员提供了一层附加的 ...
- C++顺序性容器、关联性容器与容器适配器
什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...
- C++ 容器:顺序性容器、关联式容器和容器适配器
什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象 ...
- 初步STL该容器适配器
容器适配器 特点 容器一定的顺序来实现(让现有的以集装箱堆放/式工作) 分类 1) stack: 头文件 <stack> • 栈 -- 后进先出 2) queue: 头文件 <que ...
- 容器适配器————queue
只能访问 queue<T> 容器适配器的第一个和最后一个元素.只能在容器的末尾添加新元素,只能从头部移除元素. 操作 queue<int> q;//创建一个int型的空队列q ...
- C++ Primer : 第九章 : vector变长、string的其他操作以及容器适配器
vector变长机制.string的其他构造方法,添加.替换和搜索操作,string比较和数值转换,最后是容器适配器. vector对象是如何增长的 vector和string类型提供了一些成员函数, ...
- c++ 顺序容器学习 - 容器适配器
摘要: 对 容器适配器 的疑问. 刚开始接触 容器适配器 时,总感觉怪怪的,认为多此一举,顺手搜了搜,原来我在这一点is not alone: STL容器适配器的用途 其中有个老兄说的好,这里 引用一 ...
- C++ Primer 学习笔记_33_STL实践与分析(7) --容器适配器
STL实践与分析 --容器适配器 引: 除了顺序容器.标准库还提供了三种顺序容器适配器:queue,priority_queue和stack.适配器是标准库中的概念.包含容器适配器,迭代器适配器和函数 ...
- STL之容器适配器queue的实现框架
说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章STL之容器适配器stack的实现框架已经介绍了STL是怎样借助基础容器实现一种经常使用的数据结构stack (栈),本文介绍下第二种STL ...
随机推荐
- PDO数据访问抽象层
PDO数据访问抽象层: 我们使用的mysqli是针对mysql这个数据库扩展的一个类,如果要用到别的数据库的话就可以用PDO来做 1.操作数据库 先来代码 <!--PDO--> <! ...
- Python 3 读写文件的简单方法!
Python 3 读写文件的简单方法! a = open('test.txt','w') 这行代码创建了一个名为test的文本文档,模式是写入(模式分为三种,w代表写入,r代表阅读,a代表在尾行添加) ...
- [HDUOJ1312]Red And Black (经典的DFS)
Hot~~招聘——亚信科技,巴卡斯(杭州),壹晨仟阳(杭州),英雄互娱(杭州) (包括2016级新生)除了校赛,还有什么途径可以申请加入ACM校队? Red and Black Time Limit: ...
- JavaWeb与Asp.net工作原理比较分析
一.概述 不管是什么语言开发的web应用程序,都是在解决一个问题,那就是用户输入url怎么把对应的页面响应出来,如何通过url映射到响应的类,由于自己做asp.net的时间也不短了,还算是对asp.n ...
- 使用Three.js网页引擎创建酷炫的3D效果的标签墙
使用Three.js引擎(这是开源的webgl三维引擎,gitgub)进行一个简单应用. 做一个酷炫的3d效果的标签墙(已经放在我的博客首页,大屏幕可见), 去我的博客首页看看实际效果 www.son ...
- PHP-配置方法
由于php是一个zip文件(非install版),安装较为简单,解压就行.把解压的 php5.2.1-Win32重命名为 php5.并复制到C盘目录下.即安装路径为 c:\php5 1 找到php目录 ...
- vue学习笔记(一)关于事件冒泡和键盘事件 以及与Angular的区别
一.事件冒泡 方法一.使用event.cancelBubble = true来组织冒泡 <div @click="show2()"> <input type=&q ...
- C++数据
const :常量 ~x == -++x == -(x+1) 二进制数,1变为0,0变为1 ^ 相同为0,不同为1 & ...
- 单发邮箱 群发邮箱 程序 Email winform
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- 受限玻尔兹曼机(RBM)原理总结
在前面我们讲到了深度学习的两类神经网络模型的原理,第一类是前向的神经网络,即DNN和CNN.第二类是有反馈的神经网络,即RNN和LSTM.今天我们就总结下深度学习里的第三类神经网络模型:玻尔兹曼机.主 ...