EssentialC++ 读书笔记

来源:互联网 发布:巨人网络市值 编辑:程序博客网 时间:2024/06/09 15:55

基础
1、对象的定义就是为对象命名并且说明他的类型

2、对象的初始化就是在定义的时候顺便给一个初始的值。

对象的初始化可以是直接使用赋值等号(=),或者是直接使用构造函数 int  a(3);

3、const 类型的对象必须在定义的时候进行初始化因为其他任何时间你都无法再次的修改他的值。

4、模运算的经常运用的地方就是当我们希望限制一个范围不超过多少的时候,就可以使用

5、条件表达式 a = (result)? A:B 结果取决于result的真假,为真时A为假时是B。

6、复合赋值表达式 a +=2,这种

7、递增递减运算符,需要注意的是放置的位置(前后)对变量当前数值的影响

8、逻辑运算符,以及他们之间的组合

9、运算符之间的优先级

10、条件、循环语句

11、数组和向量

数组的使用就是在定义开始的时候我们需要制定一个数组的名称以及存储于数组中的数据的类型,以及数组的大小,int a[10]像这样。

我们可以通过数组元素的下标直接的使用相对应位置上的元素。

向量是另外一种和数组相似的存储的结构,下面整理向量的相关的使用方法和知识点。

1、使用前必须要包含头文件:#include

2、定义: vector<类型>名称(大小) 举例: vector test(10),这样便是定义了一个用于存储int类型数值的长度为10 的一个向量的存储的结构。

3、使用方法:

3.1、随机位置插入,test.insert(位置,插入的数据),需要注意的是,insert使用的前插法,就是找到具体的位置,在该位置的前面插入相应的数据。

3.2、尾插法:test.push_back(插入的数据)

3.3、删除:test.clear(),删除整个的向量

3.4、有范围删除:test.erase(开始位置,起始位置)

3.5、向量的大小:test.size()返回该向量的大小

3.6、使用迭代器进行遍历:

vector::iterator it

for(it=test.begin();it!=test.end();it++)

{

///

}

3.7、使用下标直接的访问相应位置上的数据

比较:

相同点:

1、都是使用连续的存储空间存储数据

2、在开始的定义的时候都必须事先声明好要存储的数据的对象。

3、都可以使用下标对相应位置上的数据的元素进行提领。

不同点:

1、数组的长度是固定的,但是向量不一样,向量可以在开始的时候默认的直接的制定向量的初始的长度,但是在后面可以通过插入函数直接拓展

2、数组不知道自己的长度,但是向量知道(通过size()函数)

3、两者的遍历的方式不同。

12、指针

指针的定义:指针类型* 指针变量名

指针的提领:*指针变量名

指针的存储内容:

13、文件的读写

在C++中文件的读写使用的是

面向过程的编程风格
1、函数

返回值、参数、函数名、函数体

1.1、函数的值传递知识对变量进行了一次拷贝,元对象和传入函数的参数之间没有什么必然的关系。

1.2、当调用一个函数的时候,会在函数的内部建立一个栈区,用来存储所有的参数以及函数内部定义的局部的变量。

1.3、使用址传递:1、希望直接修改传入的对象的内容 2、避免拷贝较大对象影响效率

1.4、指针和引用之间的共同点就是都是传入一个对象的地址,只不过是使用方式的不同,但是指针会(也有可能不会)指向一个实际的对象,引用是一定会指向一个实际的对象。

2、参数的生存空间

2.1、对函数内部定义的局部非静态变量进行返回是没有任何的意义的,因为函数结束后当前函数的栈空间就会自动的释放。

2.2、如果一个变量被定义在一个函数体中,我们说该变量具有局部的生命周期,如果一个变量被定义在一个文件中,我们说该变量带该文件的结束时有生命周期的。

    具有文件生命周期的变量会被初始化为0,但是局部的变量如果没有认为的操作,是不会被初始化的。

3、动态内存管理

3.1、申请内存的语法:new type,例如 new int 便是申请一个Int大小的内存空间,也可以在new的时候对申请来的空间进行初始化 new type(init date values)

3.2、new申请来的空间是从堆上申请来的。

3.3、new 同样可以申请一段连续的空间,例如为一个数组申请空间,new type[arry-len] 例如: int * p= new int[10],就是申请了大小为10个的int类型的存储空间。

3.4、new申请来的空间必须手动的进行释放,使用delete ,例如:delete p;

3.5、针对数组指针的释放方式比较特别,需要在delete 和 要删除的指针中间加上中括号,例如:delete [] p;

3.6、delete一个指针变量的时候是不需要去判断该指针是否为空的,编译器会提我们做该检查。

4、函数默认参数

4.1、默认参数是从左到右依次进行读取,如果一个从一个参数开始是默认参数,那么该参数右边的所有的参数也都必须是默认的参数,所以一般都是把默认的参数放在参数列表的最右边

4.2、默认参数的标明只能有一个地方,可以是函数的声明处,或者是函数的定义处。

5、静态局部变量

5.1、静态局部变量由于存储在静态存储去,不会由于函数的执行结束而消失,能够保存上一次使用后的变量值,在某些时候很有用处。

6、inline函数

6.1、内联函数的定义就是在函数的前面加上inline关键字,一般在函数的声明的地方就会标识出该函数为一个内敛函数,而且函数的定义一般也都是在头文件中,

因为编译器在编译的时候就需要该函数的函数体在各个调用点进行展开,所以需要他有效的定义。

6.2、内联函数的作用就是针对那些体积小具有单一功能的处理单元准备的。

6.3、内联函数对提高效率是很有帮助的,一旦一个函数被声明为了内联函数,那么编译器就会在该函数的每个调用的地方将该函数展开,避免了函数的寻址。

7、函数重载

7.1、函数的重载,就是定义几个具有相同函数名,但是函数的参数个数,参数类型不同,我们称这几个函数进行了函数的重载。

7.2、函数的重载,就是为了定义实现几个相似功能的函数,但是在参数的个数和参数的类型上有差异。

7.3、为什么需要进行函数的重载就是因为C++的语言特性,进行函数重载的几个函数功能类似,只不过由于参数的不同就去定义多个函数,那样的话

就变成了数据结构引导型,但是C++是功能引导型,我们并不希望穿行于负载的数据结构上面。

8、函数模板

8.1 函数模板的作用就是针对有一些函数的参数个数和参数的顺序还有函数体的逻辑都相同,只不过由于参数的类型不同而重复定义的一些函数,

我们可以定义一个函数的模板,使用一个临时的参数类型,去定义一个函数的模板,当在实际使用该函数的时候,根据实际传入的参数的类型,函数会被重新生成

一个函数体,其中的临时类型都会被替换成实际传入的参数的类型,这就是函数模板。

8.2函数模板的定义如下:

template

void func_name(int a, tmp_type b)

{

printf("size:[%d]\n",tmp_type->size());

}

使用:

func_name(1,list);

在上面的例子中,tmp_type就是我们临时定义的一个类型,他只是一个象征性的意义,当我们传入实际的参数的时候,编译器会自动的进行替换。

9、函数模板和函数重载之间的差异

参数个数    参数顺序    参数类型    返回值 函数体      

函数重载 相同或者不同 不同 不同 相同或者不同 不相同
函数模板 相同 相同 不停 相同 相同

10、函数指针

10.1、函数指针顾名思义就是一个指针,只不过这个指针指向一个函数

10.2、定义格式: 函数返回值类型 (* 指针明名称)(形参列表)

例如:

对于函数:int * handle_test(int a ,char b, string c)

如果定义一个可以接受该函数的指针需要定义成如下:

int * (*p_func)(int,char,string)

使用:p_func(1,’a’,”aaaa”)

泛型编程
1、什么是泛型编程?

泛型编程是针对C++中的标准模板库(STL)来说的。

标准模板库有两部分组成,一部分是像map、list、set、vector等等这些容器类,另外一部分就是用来操作这些容器的一些泛型算法,比如,size find bengin end 等等。

泛型算法就是提供了一些算法,但是这些算法是可以在容器的性别和数组的类型之上的,就是说它不关心实际操作的容器的类型,所以叫泛型。

比如不管是list 还是map 都可以直接对他们就行size操作,就会返回list或者是map的大小,size算法本身并不关心实际操作的是list还是map 。

泛型算法的实现是使用了函数模板技术(function tempalte).

2、指针的算术运算:

2.1、对于vector类型的指针,由于他们是存储在连续的存储空间上的,所以当指针变量加1时就相当于是指向了下一个数据元素

2.2、数组名其实代表的是数组中第一个元素的地址,针对数组名字也可以像指针一样的操作,同事也可以进行下标操作

3、了解泛型指针(iterrator)或者是迭代器

3.1、泛型指针的要求就是:1、能够通过该指针获取到下一个元素,2、能够知道对该指针提领后的数据的类型

3.2、针对数组,数组名其实就一个泛型的指针,针对其他的STL容器来说,定义方式为:类型::iterator 指针名

例如,针对向量: vector::oterator itr;

在实际的使用的过程中,往往把迭代器指向对象的第一个元素,然后通过对迭代器的加减就可以实现对上一个或者是下一个元素的偏移,从中

可以看出,向量或者list他们本身的存储并不一样,向量是连续存储但是list不是,但是通过迭代器,将操作统一化,所以说迭代器是是一种泛型的指针,他和实际操作的容器类型无关。

4、所有容器共有的操作

4.1、相等(==)和不等(!=)

4.2、赋值(=)

4.3、size(),返回容器的大小

4.4、empty(),判断容器是否为空,当容器为空是返回真,否则返回假

4.5、clear(),清空容器

4.5、begin(),返回一个泛型指针,指向第一个元素,如果容易为空,返回0或者是NULL。

4.6、end():返回一个泛型指针,指向最后一个元素的下一个元素,这也是我们在迭代是会写(it!=vec.end())的原因

4.7、insert():插入一个元素

4.8、erase():清空容器

5、使用序列式容器

序列式容器的特点就是所有的数据单元成线性的排列。主要包括vector、list、deque

vectot:数据 单元连续存储,可以存储内建类型或者是用户自定义的类型,直接操作任意位置上的数据,中间插入或者删除效率低

list:数据单元分散存储,可以存储内建类型或者是用户自己定义的类型,直接操作任意位置上的数据效率低,插入或者是删除的效率较高。

deque:数据单元连续存储,可以存储内建类型或者是用户自定义的类型,直接操作任意位置上的数据效率低,对于头插和尾删的效率高。

使用说明:

定义:由于上述的这三种类型都是模板类,所以他们的定义都遵循: 容器类型<存储的数据类型> 容器名称 例如:vector tmp_int_vec

5.1、如果不对容器的元素进行初始化的话,那么对于数值型容器来说默认成员会被初始化为0

5.2、定义容器大小:vevtor aa(10),初始化该下向量的大小为10

5.3、定义容器大小并且初始化:vector aa(10,12),初始化该向量的大小为10,并且所有的数据元素的初始值都是12

5.4、使用已经存在的容器去初始化另外一个容器:v1 是一个容器,vecotor v2(v1)

5.5、使用泛型指针初始化一个容器:i_s和i_e是两个迭代器,vector v(i_s,i_e)

5.6、常见函数:

push_bakc(数据):尾插

pop_back(数据):尾删(不会返回删除的数据)

push_front()—–只适用于list和deque

pop_front()——只适用于list和deque,不会返回删除的数据

5.7、特殊化的删除插入

iterator insert(position,value):在position位置前面插入数值,返回一个泛型指针指向刚刚插入的位置:

void insert(position,count,value):在position位置前面把数值插入多遍:

void insert(position,iterator start, iterator end):在position位置前面插入start和end之间的所有的位置上的数值:

void insert(position):在position位置前面插入该类型的容器的默认值:

iterator erase(iterator postion):删除泛型指针所指位置,并且返回删除位置的下一个位置:

iterator erase(iterator start, iterator end)删除泛型指针所指的范围内的位置,并且返回end位置的下一个位置:

6、泛型算法

iterator find(iterator start,iterator end, typeelement):该函数在start 和end 这两个泛型指针之间进行查找数据元素typeelement,成功返回指向元素的泛型指针,失败返回end迭代器

iterator binary_search(iterator start,iterator end, typeelement):该函数的作用和find函数相同,不同的是该方法作用于有序的容器,采用的是二分法进行的排序。

iterator search(iterator start1,iterator end1, iterator start2,iterator end2):查询一个子串是不是在另外一个数据串中,如果有则返回在父串中的起始位置,没有返回父串的end

TypeElement max_element(iterator start,iterator end):该泛型方法把 位于start 和end之间的的最大值直接返回

int count((iterator start,iterator end, typeelement):返回位于指示的两个迭代器之间响应的数据的个数

copy(iterator start,iterator end,iterator start2):把位于start 和end 之间的容器数据拷贝到start2为开始的容器中,前提是start2的容器事先一定要申请足够大的空间

sort(iterator start,iterator end);对两个指示器之间的数值进行排序

7、Map

inlude

Map是属于关系型容器的一种,他使用key/value的方式存储数据,存储在map中的key值一定是唯一的。

定义:

map<键的类型,值的类型> map名称,例如:map

原创粉丝点击