STL之queue

queue 如同 stack 一般,在 STL 中队列也是作为一种适配器出现的. queue的特点: queue是队列,而队列是一种先进先出 (FIFO) 的数据结构.它允许在一端插入数据,在另一端删除数据.最先进入队列的数据最先出队列.除此之外,队列还允许访问队头元素和队尾元素,获取队列长度和判断空列队等操作. 队列不提供遍历的方法,也不提供迭代器. 几乎所有的序列式容器都支持在两端插入和删除数据元素的操作,若以某种序列式容器为底部结构,只保留其一端的插入接口和另一端的删除接口,使其符合先进先出的特性,便轻而易举的形成了一个队列. queue的使用 //构造 queue<T> queT; queue(const queue &que);//拷贝构造函数 //赋值 queue& operator=(const queue &que);//重载等号操作符 //存取 push(elem);//在末尾加入一个元素 pop();//删除第一个元素 front();//返回第一个元素 back();//返回最后一个元素 //大小 empty();//如果队列空则返回真 size();//返回队列中元素的个数

Read More

STL之list

list容器是一个双向链表,而且还是一个循环的双向链表. 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相较于vector的连续线性空间,list显得复杂许多,它的好处是每次插入或者删除一个元素,就是配置或者释放一个元素的空间。因此,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或元素的移除,list永远是常数时间。 list的特点: – 采用动态存储分配,不会造成内存浪费和溢出 – 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素 – 链表灵活,但是空间和时间额外耗费较大 list有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效.这在vector是不成立的,因为vector的插入操作可能造成迭代器重新配置,导致原有的迭代器全部失效;甚至list元素的删除,也只有被删除的那个元素的迭代器失效,其他迭代器不受任何影响。 list的使用 //构造 list<T> lstT;//list采用采用模板类实现,对象的默认构造形式: list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。 list(n,elem);//构造函数将n个elem拷贝给本身。 list(const list &lst);//拷贝构造函数。 //插入和删除 push_back(elem);//在容器尾部加入一个元素 pop_back();//删除容器中最后一个元素 push_front(elem);//在容器开头插入一个元素 pop_front();//从容器开头移除第一个元素 insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。 insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。 insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。 clear();//移除容器的所有数据 erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。 erase(pos);//删除pos位置的数据,返回下一个数据的位置。 remove(elem);//删除容器中所有与elem值匹配的元素。 //大小 size();//返回容器中元素的个数 … “STL之list”

Read More

STL之stack

stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口。stack容器允许新增元素,移除元素,取得栈顶元素,但是除了最顶端外,没有任何其他方法可以存取stack的其他元素。换言之,stack不允许有遍历行为。 有元素推入栈的操作称为:push,将元素推出stack的操作称为pop. 需要注意的是,stack没有迭代器.stack所有元素的进出都必须符合”先进后出”的条件,只有stack顶端的元素,才有机会被外界取用。stack不提供遍历功能,也不提供迭代器。 stack的用法 //构造 stack<T> stkT;//stack采用模板类实现, stack对象的默认构造形式 stack(const stack &stk);//拷贝构造函数 //赋值 stack& operator=(const stack &stk);//重载等号操作符 //存取 push(elem);//向栈顶添加元素 pop();//从栈顶移除第一个元素 top();//返回栈顶元素 //大小 empty();//判断堆栈是否为空 size();//返回堆栈的大小 //C++11中添加 emplace(elem,…);//emplace直接传入Node的构造函数的参数,并将构造的元素加入栈中;省去了构造临时对象,减少了内存开销 swap();//swap将两个 stack的内容交换.这两个 stack的模板参数 T和 Container必须都相同

Read More

STL之deque

deque是一种双向开口的连续线性空间。 所谓的双向开口,就是可以在头尾两端分别做元素的插入和删除操作.当然,vector容器也可以在头尾两端插入元素,但是在其头部操作效率奇差,无法被接受. deque容器和vector容器最大的差异,一在于deque允许使用常数项时间对头端进行元素的插入和删除操作,二在于deque没有容量的概念,因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间并链接起来,换句话说,像vector那样,”旧空间不足而重新配置一块更大空间,然后复制元素,再释放旧空间”这样的事情在deque身上是不会发生的.也因此,deque没有必须要提供所谓的空间保留(reserve)功能. 虽然deque容器也提供了Random Access Iterator,但是它的迭代器并不是普通的指针,其复杂度和vector不是一个量级.这当然影响各个运算的层面.因此,除非有必要,我们应该尽可能的使用vector,而不是deque.对deque进行的排序操作,为了最高效率,可将deque先完整的复制到一个vector中,对vector容器进行排序,再复制回deque. deque是由一段一段的定量的连续空间构成,一旦有必要在deque前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在deque的头端或者尾端.deque最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间/复制/释放的轮回,代价就是复杂的迭代器架构. 既然deque是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐.deque代码的实现远比vector或list都多得多. deque采取一块所谓的map(注意,不是STL的map容器)作为主控,这里所谓的map是一小块连续的内存空间,其中每一个元素(此处成为一个结点)都是一个指针,指向另一段连续性内存空间,称作缓冲区.缓冲区才是deque的存储空间的主体. ## deque的使用 //构造 deque<T> deqT;//默认构造形式 deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。 deque(n, elem);//构造函数将n个elem拷贝给本身。 deque(const deque &deq);//拷贝构造函数。 //赋值 assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。 assign(n, elem);//将n个elem拷贝赋值给本身。 deque& operator=(const deque &deq); //重载等号操作符 swap(deq);// 将deq与本身的元素互换 … “STL之deque”

Read More

STL之vector

vector: 向量容器,是一个能够存放任意类型(可以是char,int,double,string,或是自定义类)的动态数组,能够增加和压缩数据. 要使用vector前,需要包含头文件<vector>,并且由于vector 属于 std 命名域,因此需要通过命名限定. vector的容量 vector是一个动态增长数组. vector容量增长的本质:每次空间不够时,容器适配器会在另一个内存空间将待用空间多次的两倍扩张(1.2.4.8……..),安排好扩张内存后将所有值复制过去。 vector 对象的大小就是3个指针的大小。所有对于 vector 的操作都是基于这三个指针的。除了*与long随操作系统子长变化而变化外,其他的都固定不变(32位为4字节、64位为8字节) 。 vector的使用 //构造 vector<T> v; //采用模板实现类实现,默认构造函数 vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。 vector(n, elem);//构造函数将n个elem拷贝给本身。 vector(const vector &vec);//拷贝构造函数。 //如 使用第二个构造函数 我们可以… int arr[] = {2,3,4,1,9}; vector<int> … “STL之vector”

Read More

关于C++的STL认知

STL简介 STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。 STL它是由Alexander Stepanov、Meng Lee和David R Musser在1992年惠普实验室工作时所开发出来的。现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。 STL的版本很多,常见的有HP STL、PJ STL、 SGI STL等版本,主要流行的是SGI STL的版本。但它们的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。 在C++标准中,STL 被组织为下面的 13 个头文件:<algorithm>、<deque><functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。 算法 大家都能取得的一个共识是函数库对数据类型的选择对其可重用性起着至关重要的作用。举例来说,一个求方根的函数,在使用浮点数作为其参数类型的情况下的可重用性肯定比使用整型作为它的参数类性要高。而C++通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL就利用了这一点提供了相当多的有用算法。它是在一个有效的框架中完成这些算法的——你可以将所有的类型划分为少数的几类,然后就可以在模版的参数中使用一种类型替换掉同一种类中的其他类型。 STL提供了大约100个实现算法的模版函数,比如算法for_each将为指定序列中的每一个元素调用指定的函数,stable_sort以你所指定的规则对序列进行稳定性排序等等。这样一来,只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能并大大地提升效率。 算法部分主要由头文件<algorithm>,<numeric>,<functional>组成。 <algorithm>是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。 <numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。 <functional>中则定义了一些模板类,用以声明函数对象。 容器 在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分时,数据结构的选择就显得更加重要。 经典的数据结构数量有限,但是我们常常重复着一些为了实现向量、链表等结构而编写的代码,这些代码都十分相似,只是为了适应不同数据的变化而在细节上有所出入。STL容器就为我们提供了这样的方便,它允许我们重复利用已有的实现构造自己的特定类型下的数据结构,通过设置一些模版类,STL容器对最常用的数据结构提供了支持,这些模板的参数允许我们指定容器中元素的数据类型,可以将我们许多重复而乏味的工作简化。 容器部分主要由头文件<vector>,<list>,<deque>,<set>,<map>,<stack>,<queue>组成。对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器),可以通过下表总结一下它们和相应头文件的对应关系。 向量(vector):连续存储的元素<vector> 列表(list):由节点组成的双向链表,每个结点包含着一个元素<list> … “关于C++的STL认知”

Read More

关于C++模板的认知

模板定义: 模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。 模板特点: 1. 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型; 模板是一种对类型进行参数化的工具; 通常有两种形式:函数模板和类模板; 函数模板针对仅参数类型不同的函数; 类模板针对仅数据成员和成员函数类型不同的类。 使用模板的目的就是能够让程序员编写与类型无关的代码。 比如编写了一个交换两个整型int 类型的swap函数,这个函数就只能实现int 型,对double,字符这些类型无法实现,要实现这些类型的交换就要重新编写另一个swap函数。使用模板的目的就是要让这程序的实现与类型无关,比如一个swap模板函数,即可以实现int 型,又可以实现double型的交换。模板可以应用于函数和类。下面分别介绍。 注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。 函数模板 函数模板的格式: “` C++ template 返回类型 函数名(参数列表) { … }; 其中`template`和`class`是关见字,`class`可以用`typename` 关见字代替,在这里`typename` 和`class`没区别,`<>`括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。一但声明了模板函数就可以用模板函数的形参名声明类中的成员变量和成员函数,即可以在该函数中使用内置类型的地方都可以使用模板形参名。模板形参需要调用该模板函数时提供的模板实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。比如swap的模板函数形式为 “` C++ template <class T> void … “关于C++模板的认知”

Read More

如何学好C++(转)

昨天写了一篇如何学好C语言,就有人回复问我如何学好C++,所以,我把我个人的一些学习经验写在这里,希望对大家有用。首先,因为如何学好C语言中谈到了算法和系统,所以这里就只谈C++语言。 C++是最难的语言。这个世界上最难的编程语言可能非C++莫属了。你千万不要以为几天就可以学好C++,C++的学习曲线是相当BT的,你可以看看这篇文章。C++是一门很自由的语言,自由到了有点BT和恐怖的地步。我甚至认为C++并不是一门成熟的编程语言,因为太容易犯错了。所以,你一定要在一开始就要有很小心谨慎的态度,并把C++当成一种难以训服的猛兽来看待。 多问“为什么要这样”的问题。学习C++一定要多问几个“为什么是这样”,“凭什么要这样”的问题。比如:很多人知道C++有拷贝构造函数和初始化列表,但你真的知道为什么要有拷贝构造函数?为什么要有初始化列表吗?为什么要有template,为什么要有RTTI,为什么不是别的呢?难道就是为了让一门语言变得Cool一些吗?完全不是这样的,C++中的任何一个feature都有些实实在在的原因,你一定要去了解为什么要把C++设计成这样的原因,你才能学好C++。有空看看《C++演化和设计》一书。 看书,大量的C++书。你可以按如下先后顺序阅读(下面这些书,我花了大约4-5年的时间,今天我还在随时温习) 《C++ Primer》,这本初级读本可能让会你啃得很痛苦,所有的语言的特性和为什么都在里面了,好好读读。当然由C++之父写的《C++程序设计语言》也不错。两本看一本就好了(我看的是前者)。 了解C++的语法仅仅是万里长征的第一步,你还需要看看《Effective C++》和《More Effective C++》这两本书并不厚,但我从02年就一直看到现在,每次读我都有新的体会,这两本书太经典了。如果你对C语言不熟,这两本书会让你回去补C语言的课。 《Think in C++》同样是另一本经典之极的书,学c++必读,但是中文版的翻译的很不好,所以还是去读英文版的吧。 《C++沉思录》同样非常值得一读,这里教的不是编程,而是思考的方法,这是相当珍贵的。 《Exceptional C++》和《More Exceptional C++》让你看看各种问题的解决方法和一些常见的经典错误。 《Advanced C++》和《Modern C++》可以让你知道C++各种神奇的用法。 《泛型编程与STL》是把C++实践到了极致的东西。很强大。STL——神一样的模板库(容器,算法和函数对象),不得不服。 《深入探索C++对象模型》让你了解编译器下的C++是什么样的,让你了解C++的性能并不差。这个对于C++的程序员太关键了。我以前写过的《C++虚函数表解析》还有《C++对象内存布局》属于这个范畴。 和Java语言做对比。我个人以为Java对C++这个并不成熟的语言做了很多调整,规范和限制。所以,对比一下Java和C++,想一想,为什么一些东西在C++中可以做,但在Java中却不行。比如:Java的异常是必需要catch的,不然就会编译不通过。为什么Java不提供操作符重载?为什么Java会引入接口来做多重继承?为什么Java没有像C++那样的I/O字符流?为什么Java不支持指针?为什么Java可以做到垃圾回收?等等。Java体现着很多面向对象设计的东西,学习Java有助于你学会怎么更好地使用C++来编程。 面向对象设计。虽然面向对象可能是个骗局。但是我觉得面向对象设计中的一些实践非常的不错,比如,单一原则,依赖倒置原则,等等,都非常地经典。《设计模式》必需一读,《面向对象的分析和设计》可以一读。但不可以设计模式为中心来编程,而应该是用设计模式来解藕。 类库学习。看看MFC是怎么封装Windows API的,看看ACE是怎么面向对象的,看看boost是怎么玩面向对象的,看看CPPUnit又是怎么设计的。当然,Java的JDK中有太多的设计模式,可以参考。 希望没有吓到大家,并欢迎大家补充。 —————更新 2011/03/30 19:20———— 更新几个观点: 1)我不擅长写书评,所以推荐的这些书可能会让你有点看点没有感觉,你可以上豆瓣或是China-pub上看看书评。 2)C++有很多奇淫技巧,有的很BT,包括虚函数表,也许会有人觉得有点没意思,但我觉得很有意思,一方面可以了解一门语言的实现细节,另一方面可以开阔思路。我从学习这些知识中受益很多。 3)上述是我的个人的学习历程,我觉得对我很有效,所以是经验之谈。 … “如何学好C++(转)”

Read More

如何学好C语言(转)

我相信,这可能是很多朋友的问题,我以前也有这样的感觉,编程编到一定的时候,发现能力到了瓶颈,既不深,也不扎实,半吊子。比如:你长期地使用Java和.NET ,这些有虚拟机的语言对于开发便利是便利,但是对于程序员来说可能并不太好,原因有两个: 虚拟机屏蔽了操作系统的系统调用,以及很多底层机制。 大量的封装好的类库也屏蔽了很多实现细节。 一段时间后,你会发现你知其然,不知所以然…我以前在CSDN上写过一篇《Java NIO类库Selector机制解析(上,下,续)》,在那篇文章中我说提到过(有讥讽的语气)Java的程序员不懂底层实现,所以很难把技术学得更扎实。此时,一部分程序员会不自然地想学学底层的技术,很自然的,C语言就被提了上来。 下面是我给这位朋友的一些建议: 鼓励并为你叫好。我鼓励你想要去学C语言的想法和精神,很多人都觉得C语言好学,其实并不然。(你可以看看《C语言的迷题》)现在的这个社会更多地去关注那些时髦的技术,而忽略了这个流行了40+年的C语言。一门技术如果能够流行40多年,这才是你需要去关注和学习的技术,而不是那些刚出来的技术(过度炒作的技术,Windows编程史)。这才是踏踏实实的精神。 不要找借口。这一条路走下来并不容易,不要给自己找借口。我最不喜欢听到的就是“很忙,没有时间”这样的借口。我以前在银行做项目,早9点到晚10点,周一到周六,我一样可以每天抽1个小时来看书和专研,一年下来也能精读5、6本书。我现在的工作项目和招聘任务很紧张,刚生的小孩只有自己和老婆两人带,还需要准备讲课,但是我还是能够找到时间看文章写文章维护酷壳。所以,我可以告诉你,“时间就像乳沟,只要你肯挤,就一定会有”。 学好C语言和系统编程。我认为,学好编程有四个方面:语言、算法和数据结构、系统调用和设计。 语言。我可以告诉你C语言有两大主题你要好好学,一个是内存管理,一个是指针!这个世界上90%以上的C/C++出的严重性错误全是和这两个有关。不要看谭浩强的那本书,那本是本烂书。推荐这本书给你《C程序设计语言(第2版·新版)》 算法和数据结构。我认为,用C语言实现算法和数据结构莫过于最爽的事情。推荐你看这本书——算法:C语言实现(第1~4部分)基础知识、数据结构、排序及搜索(原书第3版),还有那本经典的《算法导论》 系统编程。Windows下推荐两本书——《Windows 程序设计》和《Windows核心编程》,Unix/Linux下推荐两本书——《Unix高级环境编程》和《Unix网络编程卷1,套接字》《Unix网络编程卷2,进程间通信》尤其是《Unix网络编程》这本书,一通百通,无论Windows还是Unix/Linux,都是一样的。 系统设计。关于设计方面,我全力推荐《Unix编程艺术》,看完以后,你就明白什么是真正的编程文化了。然后,当你看到Windows的Fans的某些言论时,你就知道什么叫一笑了之了。 如果你能在2-3年内精读完这些书,并全部融会贯通,那么你就明白什么是一览众山小的感觉了!我足足花了5年时间才算是真正全部读完这些书的。最后,祝你好运!努力! ——-更新:2011/03/29 20:00——- 我想,这篇文章主要想告诉大家这么几件事: 编程编到一定时候,你就需要了解底层系统的机制,否则,知其然不知所以然。 我没有否定非C的程序员的逻辑,真正的逻辑是——如果你想要了解底层机制,请学习C语言和操作系统。 40多年的Unix/C影响深远。包括影响了Windows。如果你想一通百通,一定要了解Unix。那是计算机文化真正的根。 不要肤浅地去思考问题。比如,不要以为一个DBA就不会考虑数据库引擎的内存页面的问题。也不要以为Web程序员就不需要了解后台的服务器和脚本的运行性能以及TCP/IP的问题。 高手往往都是有很强的系统的基础知识的,表面的东西永远是肤浅的。

Read More

关于class和struct的认知.

花了几周的时间看了<<C++ Primer>>并模仿了点代码,感觉C++与C的关系就像vim与vi的关系.扩展了C,但是完完全全的兼容C. 总结了两者间的差异: – C++中的class关键字完全可以当作struct用,但因为它比struct多出的功能,又有些微的不同. – 基于class,C++有了内联inline,当然也可以不限于class中使用. – 定义在类中的成员函数缺省都是内联的,并且内联函数不可过于复杂,内联函数不能使用循环语句和递归. – inline仅是一个对编译器的建议,如果编辑器认为函数过于复杂,则会放弃内联. – 基于class,C++有了多态,继承,虚继承,虚函数,纯虚函数. class的数据成员在内存中的布局不一定是数据成员的声明顺序,C++只保证处于同一个access section的数据成员按照声明顺序排列. 在C++中,class和struct做类型定义是只有两点区别: – 默认继承权限不同,class继承默认是private继承,而struct默认是public继承. – class还可用于定义模板参数,像typename.但是关键字struct不能同于定义模板参数. C++保留struct关键字,原因: – 保证与C语言的向下兼容性,C++必须提供一个struct – 且为了百分百地保证与C语言中的struct的兼容性,把C++中的最基本的对象单元规定为class而不是struct,就是为了避免各种兼容性要求的限制. – 对struct定义的扩展使C语言的代码能够更容易的被移植到C++中.

Read More