C++
文章平均质量分 64
Mirevas
这个作者很懒,什么都没留下…
展开
-
C++标准库STL体系结构与内核分析
总结泛型编程,就是以模板为主要工具来编写程序STL是范型编程最成功的作品,以下是根据STL探讨泛型编程目标使用C++标准库认识C++标准库(深入认识C++标准库,非常清楚部件在内存中的实现)良好使用C++标准库(熟悉标准库的体系结构)扩充C++标准库标准库一个C++编译器会提供很多头文件,以文件而不是编译好的东西,可以看到源代码,这就是c++标准库c++标准库包括STL以及一些其它的小组件一、STL体系结构与基础介绍STL六大部件简介、容器的遍历对应1原创 2021-10-20 14:42:03 · 161 阅读 · 0 评论 -
(十六)一个万用的hashfunction
customer是元素,要将它放到容器中为它写hash function,左边是成员函数版本,右边是非成员函数版本左边的形式,传入模板参数时传入的是类的名称。创建对象时,函数对象会被自动创建调用。右边的形式,传入的第二个参数是函数的类型。在创建真正的对象时还要传入函数的地址。都是在第四步修改seed,最终返回seed版本三:为模板写一个特化版本版本三的示例...原创 2021-10-07 18:26:14 · 120 阅读 · 0 评论 -
(十五)适配器adapters
适配器简介adapter更像是一个换肤工程,如把参数的个数改一下或者把函数的名称改一下。适配器根据它所改的对象分为三类函数适配器迭代器适配器容器适配器适配器更像是一个桥梁,只是修改接口,并不自己实现真正的功能适配器都是用内含的方式实现对另一个东西的控制容器适配器stack、queue二者都内含了一个sequence,默认是deque。将容器的所有接口封装为个别的几个,或者将容器的接口封装后修改其名称template <class T, class Sequence =原创 2021-10-07 17:52:55 · 93 阅读 · 0 评论 -
(十四)仿函数functors
仿函数简介functor是最有可能自定义融入到标准库中,辅助实现一些功能仿函数只为算法服务仿函数的语法functors必需重载小括号仿函数就是一个重载了小括号的类,这样的一个类所创建出来的对象就是函数对象,因为这个对象像一个函数。标准库中的仿函数分为三类算术类逻辑运算类相对关系类(比大小)template<class T>struct plus : public binary_function为什么需要仿函数,而不是直接使用运算符原创 2021-10-06 19:46:28 · 99 阅读 · 0 评论 -
(十三)STL部分算法简介
c++标准库提供的算法qsort不是c++标准库的算法,它们是c的函数qsort(c.data(), ASIZE, sizeof(long), compareLongs);long *pItem = (long*)bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs);c++标准库算法一定是在std中,且前几个参数一定都是迭代器,要使用这种方式访问容器数据算法accumulateaccumulate是累原创 2021-10-06 19:10:52 · 100 阅读 · 0 评论 -
(十二)迭代器的分类
标准库算法从语言层面来看容器Container是class template算法Alogorithm是function template迭代器Iterator是class template仿函数Functor是class template适配器Adapter是class template分配器Allocator是class template算法看不到迭代器,它所需要的一切信息都必需从Iterstor取得,而迭代器必需能够回答算法的所有问题,才能搭配算法的所有操作//同一个算法可能原创 2021-10-03 22:45:00 · 730 阅读 · 0 评论 -
(十一)hashtable
hashtable有N个元素,这些元素要放到容器中,且每个元素都可以转化为一个数值。这些元素的个数变化范围是0~2的32次方-1,需要至少2的32次方个元素的大小由于不可能准备这么大的空间,且元素的个数也不一定到2的32次方。对每个元素编号,采用取余法确定元素要放置的地点,如果容器长度为H,元素的编号为M,则将它放置到M%H处如果当前位置已经有元素了,则发生了冲突,将它跟在当前元素的后面(采用链表)如果一个节点的链表太长,就要将该链表打散重排。经验法则是,当元素个数大于篮子的个数,就要将链表打散。原创 2021-10-03 11:54:45 · 97 阅读 · 0 评论 -
(十)红黑树、set、map
红黑树红黑树是高度平衡的二叉搜索树。它的排列规则有利于serach和insert,并保持深度平衡即没有任何一个节点太深。红黑树提供遍历操作及迭代器,遍历得到一个有序序列(中序遍历)不应该使用迭代器修改红黑树节点的值,对于map,可以修改value,对于set,不能更改,防止破坏红黑树的有序性。红黑树提供两种插入操作,一种是insert_unique()另一种是insert_equal()。前者表示节点的key在整棵树中是独一无二的,后者允许节点的key重复,且相同key一定是相邻的。// Ke原创 2021-10-02 23:37:42 · 216 阅读 · 0 评论 -
(九)deque深度剖析、queue、stack
deque的实现deque是双向开口的一段空间,实质上是分段连续的具体实现如下图,先分段,再将它们串接起来。底层是一个vector,存放指向每一个缓冲区的指针,缓冲区的次序与vector的次序相同。最后一个缓冲区已经被元素填满,再分配一个缓冲区,把它串接到底层的vector中,就可继续向后扩充。如果向前扩充的缓冲区也被填满,再分配一个缓冲区,vector中靠近左端元素的空位置存储新分配缓冲区的指针。当控制中心满了后,会扩容为原来的二倍,类似vector的动态增长。deque的迭代器是一个class原创 2021-10-02 14:34:16 · 101 阅读 · 0 评论 -
(八)array、forward_list的实现
arrayarray本身是c语言中已经存在的数组,为什么还要包装成容器array被包装成一个容器,要遵循容器的规则,要提供iterator且迭代器要提供五种相应的类型,以便于让算法获得必要的信息,方便算法采取最优化的操作如果没有包装,array就被排斥在标准库六大部件之外,无法直接与算法、仿函数等等交互arrayTR1版TR1是介于c++98和c++11之间的一种版本array没有构造函数与析构函数template<typename _Tp, std::size_t _Nm原创 2021-10-01 13:37:26 · 106 阅读 · 0 评论 -
(七)vector深度剖析
容器vector的实现vector是一种动态增长的数组,在数组用完的时候,它会自动扩充。没有任何一种东西在内存中可以原地扩充,在当前数组用完后,它会在内存的另一个地方,重新开辟一个当前数组容量二倍大小的数组,将当前的元素全部移过去2.9版vector中有三个指针,start指向vector的起始位置,finish指向vector的最后一个元素,end_of_storage指向容器的最后一个空槽位的下一个位置。template <class T, class Alloc = alloc&原创 2021-10-01 13:12:38 · 226 阅读 · 0 评论 -
(五)List深度剖析
容器list的实现本质是一个环状的双向链表GNU C++ 2.9版链表大小是4,是一个指向链表节点类型的指针节点有三个变量,分别是指向前驱节点的指针,指向后继节点的指针,储存数据所有的容器,除了vector和array,它的迭代器都必须是class,它才能成为一个智能指针。为了接口的一致,它必然要typedef为iterator.所有的迭代器类都分为两部分,一部分是typedef,另一部分是操作符重载操作符重载可以看成是向偶像致敬,它的偶像就是整数。最好的类的设计是将类的使用像整数一原创 2021-09-29 22:09:32 · 135 阅读 · 0 评论 -
(四) 分配器allocator
分配器一般不建议直接使用分配器,它给容器分配内存,分配器的效率高低会直接影响容器的效率,包括速度和空间所有的分配动作,最终都会调用malloc(),这个函数再根据当前所处的操作系统不同,调用不同的操作系统API,拿到真正的内存mallocoperator new()和delete底层都调用malloc()malloc分配如下图,蓝色的内存,再搭配一整包东西返回附加的额外空间基本是固定的,如果所需的内存大,额外开销就小,如果所需的内存小,额外开销就大加的东西详细见内存管理all原创 2021-09-29 16:22:30 · 178 阅读 · 0 评论 -
(三)面向对象编程与泛型编程比较
OOP面向对象要有class与class,以及之间的继承关系、虚函数面向对象编程企图将datas与methods绑在一起GP泛型编程是将datas和methods分开来标准库中用容器存储数据,用算法处理数据算法的操作通过迭代器确定操作范围,访问容器中的元素优点容器和算法的开发团队可以独立开发,只要双方之间将接口规定好所有的算法,其最终涉及元素本身的操作,无非就是比大小bool strLong(const string& s1, const string&a原创 2021-09-29 13:07:34 · 566 阅读 · 0 评论 -
(二)顺序容器、关联容器的简介
容器的结构与分类容器可分为两类顺序容器关联式容器顺序容器有五个,是按照放入容器的顺序排列的Array数组,容量固定的连续空间Vector,后面是可以扩充的顺序容器,它的自动增长由分配器处理内存实现Deque双端队列,两端可进可出,前后均可以扩充List双向链表,节点之间通过前后指针连接Forward-List单向链表关联容器,适用于有大量查找动作的场合,底层实现是红黑树Set,key就是value,放入的元素不能重复Multiset,key就是value,放入的原创 2021-09-28 23:06:18 · 218 阅读 · 0 评论 -
(一)STL六大部件简介、容器的遍历
STL六大部件容器Containers分配器Allocators算法Algorithms迭代器Iterators适配器Adapters仿函式Functors六个组件之间的关系最常使用的是容器,容器要放东西,东西要占内存容器的使用不需要考虑内存设计,它背后有分配器支持容器容器里面放了东西要进行操作,除了容器本身的一些操作外,还有许多的模板函数,就是算法用算法处理容器的数据要访问元素,实现这个桥梁的就是迭代器,相当于一种泛化的指针仿函数的作用像是一种函数,实现自定义类对象之间的原创 2021-09-28 15:05:38 · 122 阅读 · 0 评论 -
侯捷 c++ 程序设计II 兼谈对象模型总结
总结泛型编程和面向对象编程深入探索面向对象中对象间的继承关系在内存里的结构,包括隐藏在底层的this指针,vptr虚指针,vtbl虚表,virtual mechanism虚机制,以及虚函数造成的多态。一、类的设计类型转换函数、类指针类、类函数类、namespace对应2、3、4、5、6节二、模板类与模板函数类模板、函数模板、成员模板、特化与泛化、模板模板参数对应7、8、9、10、11、12节三、部分c++11常用特性可变参数模板、auto、范围for对应13、14节四原创 2021-09-28 00:29:30 · 106 阅读 · 0 评论 -
(五)new和delete
new的实现Complex* pc = new Complex(1, 2);//编译器转化为三步void* mem = operator new(sizeof(Complex)); //分配内存pc = static_cast<Complex*>(mem); //将void指针转换为所需类型的指针pc->Complex::Complex(1, 2); //构造函数 第一步调用operator new,内部调用malloc(n),分配所需大小的内存。指针原创 2021-09-28 00:28:46 · 82 阅读 · 0 评论 -
(四)引用、对象模型、虚指针和虚表、this指针
引用从内存的角度去看,变量有三种,一种是值value,一种是指针,一种是引用大小32位电脑上,int是四个字节,double是四个字节,指针也是四个字节引用是其所引用对象的别名,但是引用的实现都是指针,引用的大小就是它所绑定对象的大小,即sizeof引用和sizeof它所绑定的对象得到的结果是相等的。对引用取地址与对它所绑定到对象取地址得到的是一样的结果。引用一定要有初值,引用一旦被定义就不能改变绑定的对象引用的常见用途参数传递,传入函数参数,返回值传递引用传递效率高,且调用接口与原创 2021-09-27 21:10:33 · 176 阅读 · 0 评论 -
(三)可变参数模板、auto、范围for
关于c++标准库分为四个部分:容器、迭代器、算法、仿函数容器顺序容器:数组、向量、双端队列、单向链表、双向链表容器适配器:栈、队列、优先队列关联容器:set、map、multiset、multimap无序关联容器:unordered_set、unordered_map、unordered_miltiset、unordered_multimap可变参数模板允许写任意个数的模板参数,使用关键字typename…语法将参数分为两部分,一个和一包可以使用sizeof…(args),求原创 2021-09-27 15:05:27 · 121 阅读 · 0 评论 -
(二)类模板、函数模板、成员模板、特化与泛化、模板模板参数
类模板与函数模板类模板template <typename T>class complex{public: ...private: T re, imag; ...};函数模板template<class T>inline const T& min(const T& a, const T& b){ return b < a ? b : a;}成员模板类是一个模板,类的成员是另一个模板,二者可以不同步变原创 2021-09-26 19:59:53 · 349 阅读 · 0 评论 -
(一)转换函数、像指针类、像函数类、namespace
转换函数class Fraction{public: Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den){ } operator double() const{//类型转化函数 return (double)(m_numerator / m_denominator); }private: int m_numerator; int m_denominator;};将一个类类型转换为一个原创 2021-09-26 09:47:03 · 87 阅读 · 0 评论 -
侯捷 c++ 面向对象程序设计总结
目录一、类的设计初步类的设计初探,关于不涉及指针的类防卫式声明、头文件布局、inline、访问级别、构造函数对应1、2、3节二、complex类的设计与实现complex类的设计过程const函数、运算符重载、参数传递、返回值传递对应4、5、6节三、String类的设计与实现关于带指针的类的设计构造函数、析构函数、拷贝构造函数、拷贝赋值运算符new和delete对应7、8、9节四、单个类的设计所需的其余知识static、函数模板对应10节五、类与类之间的关系原创 2021-09-25 17:01:05 · 277 阅读 · 1 评论 -
(五) 类与类之间的关系:继承、复合、委托
类与类之间的关系Object Oriented Programming OOPObject Oriented Design OOD类和类之间的关系复合composition继承inheritance委托delegation复合表示has-atemplate <class T, class Sequence = deque<T> >class queue{ ...protected: Sequence c;//底层容器public: //以下完全利原创 2021-09-25 16:54:13 · 464 阅读 · 0 评论 -
(四)static、函数模板
static每个类的对象都有一个默认的this指针,它指向调用成员函数的对象,通过this指针访问对象的数据静态数据一个类只有一份,例如银行账户类中的利率设计为静态数据静态函数没有this指针,不能像一般的成员函数那样去访问类数据,只能处理静态数据class Account{public: static double m_rate;//利率的声明 static void set_rate(const double& x){ m_rate = x;}//设置利率};double原创 2021-09-24 20:24:01 · 378 阅读 · 0 评论 -
(三)带指针的String类的设计与实现、堆栈与内存管理
string类的框架//string.h#ifndef __MYSTRING__#define __MYSTRING__class String{ ...};String::function(...)...Global-function(...)...#endifstring类的设计class String{public: String(const char* cstr = 0); String(const String& str); String&原创 2021-09-24 16:57:23 · 226 阅读 · 0 评论 -
(二)const、参数传递、返回值传递、类设计中的细节
class complex{public: complex(double r = 0, double i = 0):re(r), im(i){} complex() : re(0), im(0){} //不能通过编译,会有二义性 //当构建一个无参的complex对象时,第一个构造函数有缺省值,故二者均为候选函数,编译器无法确定到第调用哪个 complex& operator += (const complex&);//传加const的引用,传入的数据不能被改变 double原创 2021-09-24 01:12:57 · 118 阅读 · 0 评论 -
(一) 防卫式声明、头文件布局、inline、访问级别、构造函数
内联函数inlineinline函数运行速度快所有在类中实现的函数均是inline函数,但是最终是否成为inline函数是看编译器的实现。编译器会将较简单的函数实现为inline。在类中实现函数,或在类外实现函数且加inline修饰词,表示希望该函数为inline函数访问级别private、public所有的数据均为private需要提供给外界使用的函数为public为了实现很好的封装,数据要通过类的public函数被访问或修改如果有些函数并没有打算被外界调用,仅仅是在内部做一些处理原创 2021-09-23 09:39:19 · 123 阅读 · 0 评论 -
4.12 c++运算符优先级
运算符优先级表原创 2021-09-04 20:43:56 · 48 阅读 · 0 评论 -
4.1 c++左值和右值、类型转换
左值和右值c++的表达式不是右值就是左值。一个左值表达式的求值结果是一个对象或一个函数,然而以常量对象为代表的某些左值实际上不能作为赋值语句的左侧运算对象。此外,虽然某些表达式的求值结果是对象,但它们是右值而非左值。当一个对象被用作右值时,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(在内存中的位置)一个重要的原则是在需要右值的地方可以用左值来代替,但是不能把右值当作左值(也就是位置)使用。当一个左值被当作右值使用时,实际使用的是它的内容(值)。赋值运算符需要一个左值作为其原创 2021-09-04 20:38:09 · 1365 阅读 · 0 评论 -
2.5 类型别名、auto、decltype
处理类型随着程序越来越复杂,程序中用到的类型也越来越复杂,这种复杂性体现在两个方面。一是一些类型难于拼写,它们的名字既难记又容易写错,还无法明确体现其真实目的和含义二是有时候搞不清楚到第需要的类型是什么,程序员不得不回过头去从程序的上下文寻找帮助。类型别名类型别名是一个名字,它是某种类型的同义词。使用类型别名让复杂的类型名字变得简单明了、易于理解和使用。有两种方法可以定义类型别名方法一:使用关键字typedeftypedef double wages;//wages是doubl原创 2021-09-03 09:54:08 · 123 阅读 · 0 评论 -
2.4 const限定符
const简介const关键字对变量的类型加以限制,使得它的值不能被改变。例如,用一个变量表示缓冲区的大小。使用变量的好处是当我们觉得缓冲区大小不合适时,很容易对其进行调整。另一方面,也随时警惕防止程序一不小心改变了这个值。因为const对象一旦创建后其值就不能再改变,所以const对象必需初始化。初始化和const与非const类型相比,const类型能完成其中的大部分操作,主要的限制就是只能在const类型的对象上执行不改变其内容的操作。默认状态下,const对象仅在文件内原创 2021-09-02 22:04:16 · 88 阅读 · 0 评论 -
2.3 c++复合类型、引用和指针
复合类型复合类型是指基于其它类型定义的类型。一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成。每个声明符命名了一个变量并指定该变量为与基本数据类型有关的某种类型。引用引用(reference)为对象起了另一个名字,引用类型引用(refers to)另外一种类型。通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名。int ival = 1024;int &refVal = ival; //refVal指向ivalint &refVal2;/原创 2021-09-01 20:31:30 · 124 阅读 · 0 评论 -
2.2.2 c++中变量声明和定义
变量声明与定义的关系为了允许把程序拆分成多个逻辑部分编写,c++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。为了支持分离式编译,c++语言将声明和定义区分开来。声明使得名字为程序所知,一个文件如果想使用别处定义的名字则必需包含对那个名字的引用。定义负则创建与名字关联的实体。变量声明规定了变量的类型和名字,在这一点上定义与之相同。但除此之外,定义还申请存储空间,也可能会为变量赋一个初始值。如果想声明一个变量而非定义它,就在变量名前添加关键字extern,原创 2021-09-01 18:51:56 · 116 阅读 · 0 评论 -
2.2.1 c++变量初始化
初始值当对象在创建时获得了一个特定的值,就说这个对象被初始化了。在c++语言中,初始化和赋值是两个完全不同的操作。初始化的含义是创建变量时赋予其一个初始值。赋值的含义是把对象的当前值擦除,而以一个新的值来代替。列表初始化当用于内置类型的变量时,这种初始化有一个特点:如果使用列表初始化且初始值存在丢失信息的风险,则编译器将报错long double ld = 3.1415926536;int a{ld}, b = {ld};//错误:转换未执行,因为存在丢失信息的危险int c原创 2021-09-01 16:45:00 · 57 阅读 · 0 评论 -
2.1 C++基本内置类型
算术类型算术类型分为两类:整型和浮点型算术类型的尺寸在不同机器上有所差别。下图列出了c++标准规定的尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸。某一类型所占的比特数不同,它所表示的数据范围也不一样。除字符类型和布尔类型外,其它整型用于本身不同尺寸的整数。c++语言规定一个int至少和一个short一样大,一个long至少和一个int一样大,一个long long至少和一个long一样大。大多数计算机以2的整数次幂个比特作为块来处理内存,可寻址的最小内存块称为“字节byte”,存储的基本单元原创 2021-09-01 11:27:51 · 197 阅读 · 1 评论 -
1.2 iostream库简介
iostream库iostream库包含两个基础类型istream和ostream,分别表示输入流和输出流一个流就是一个字符序列,是从IO设备读出或写入IO设备的流想要表达的是,随着时间的推移,字符是顺序生成或消耗的标准输入输出对象标准库定义了四个IO对象名为cin的istream类型对象,也称为标准输入对象名为cout的ostream类型对象,也称为标准输出对象名为cerr的ostream类型对象,通常用来输出警告和错误信息,也被称为标准错误名为clog的ostream类型对象,用原创 2021-08-31 21:30:37 · 2173 阅读 · 2 评论