【快速学习系列 - 阅读笔记 - 09】《高质量C/C++编程指南》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangsgyx/article/details/83103944

1)头文件的作用:通过头文件来调用库功能;加强类型安全检查。

注1:头文件中通常存储着被外部调用的API,以及共用的数据结构。

2)编译器就是将“高级语言”翻译为“机器语言”的程序。

注1:机器语言是一种指令集的体系,是CPU可以直接解读的数据。

注2:高级语言是相对而言,是以人类自然语言为基础,高度封装过的编程语言,更有利于人类与计算机的交互。

3)代码编译流程:

4)交叉编译就是在一个平台(体系结构/操作系统)上生成另一个平台上的可执行代码。

5)要进行交叉编译,需要在主机平台上安装对应的交叉编译工具链,然后用其编译源代码,最终生成可在目标平台上运行的代码。常见的交叉编译例子:在Winows PC上,利用ADS,使用armcc编译器,则可编译出针对ARM CPU的可执行代码。

6)以Linux作为主机操作系统,搭配一个交叉编译系统,为嵌入式设备生成可执行程序已成为现在最为流行的编译嵌入式软件的解决方案。

7)脚本是批处理文件的延伸,是一种纯文本保存的程序。

一般来说的计算机脚本程序是确定的一系列控制计算机进行运算操作动作的组合。

脚本程序在执行时,由系统的一个解释器将其一条条的翻译成机器指令,并顺序执行。

8)无论是float还是double类型的变量,都有精度限制。

注1:float = 1bit(符号位) + 8bits(指数位) + 23bits(尾数位),精度为6~7位

double = 1bit(符号位) + 11bits(指数位)  + 52bits(尾数位),精度为15~16位。

9)常量是一种标识符,其值在运行期间恒定不变。

注1:常量是只读变量,只能被读取。

10)const数据成员只在某个对象的生存期内为常量,对于整个类而言,是相对可变的。

因为类可以创建多个对象,不同对象的const数据成员的值可以不同。

11)不能在类声明中初始化const数据成员,其初始化只能在类构造函数的初始化表中进行。

12)应当使用类中的枚举常量来建立在整个类中都恒定的常量。

注1:枚举常量仅适用于恒定整数的应用场景。

13)枚举常量不会占用对象的存储空间,其在编译时被全部求值,

缺点是它的隐含数据类型为整型,最大值有限,且不能表示浮点数。

14)C++中规定任何C++/C函数都必须有类型。

15)在C/C++中,函数的static局部变量是函数的“记忆”存储器。

16)若程序在assert处终止,并不代表含有该assert的函数有错误,而是调用者出错。

注1:assert终止时,需要向其上一级code查找问题点。

17)使用断言捕捉不应该发生的非法情况。

18)引用的主要功能是传递函数的参数和返回值。

19)使用引用的规则:

引用被创建的同时必须初始化;

不能有NULL的引用,

引用必须与合法的存储单元相关联;

一旦引用被初始化,就不能改变引用的关系。

20)内存分配方式:

第一,从静态存储区分配,内存在编译时分配,整个程序运行期间均存在,如static变量或全局变量;

第二,在栈上创建;

第三,从堆上分配,亦称为动态内存分配。

21)数组要么在静态存储区被创建,要么在栈上被创建。

22)指针可以随时指向任意类型的内存块。

23)常量字符串的内容是不可修改的。

24)C/C++没有办法获取指针所指的内存容量,除非在申请时记住它。

25)编译器总是要为函数的每个参数制作临时副本。

26)free和delete只是将指针所指的内存释放掉,指针地址仍然不变,只是该地址对应的内存是垃圾,指针变为“野指针”。

27)“野指针”不是NULL指针,而是指向垃圾内存的指针。

其主要成因有:指针变量未初始化;指针被free或delete,但未置为NULL;指针操作超越了变量的作用范围。

28)不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。

29)通常处理内存耗尽的方式:判断指针是否为NULL,若是则return或exit(1)终止;为new和malloc设置异常处理函数。

30)malloc返回为void*,故在使用时需要显式地将其转换为所需的指针类型。

31)free可以对NULL指针一直操作,但是非NULL指针只能操作一次。

32)只能靠参数的不同来区分重载函数,编译器根据参数为每个重载函数产生不同的内部标识符。

33)由于数字本身没有类型,将数字作为参数时会自动进行(隐式)类型转换。

34)重载的特征:相同的范围(在同一个类);函数名相同;参数不同;virtual关键字可有可无。

35)覆盖是指派生类函数覆盖基类函数,

特征是:不同范围(分别位于基类和派生类);函数名相同;参数相同;基类函数必须有virtual关键字。

36)隐藏是指派生类的函数屏蔽了与其同名的基类函数。

37)参数缺省值只能出现在函数的声明中,而不能出现在定义体中。

38)在C++中,可以用关键字operator加上运算符来表示函数,称为运算符重载。

39)由于C++支持函数重载,故能将运算符当成函数来使用,而C不能。

40)C++支持函数内联,其目的是为了提高函数的执行效率(速度)。

41)C中可以使用宏代码提高执行效率,其缺点是容易出错,预处理器在复制宏代码时常会产生意想不到的边际效应。

42)关键字inline必须与函数定义体放在一起才能使函数成为内联,仅将其放在函数声明前不起作用。

43)定义在类声明中的成员函数将自动成为内联函数。

44)内联是以代码膨胀为代价,省去函数调用开销,从而提高函数的执行效率。

45)每个类只能有一个析构函数和一个赋值函数,但是可以有多个构造函数(包含一个拷贝构造函数,其它为普通构造函数)。

46)构造函数有个特殊的初始化方式叫“初始化表达式表”(简称初始化表)。

初始化表位于函数参数表之后,却在函数体之前。

47)若类存在继承关系,派生类必须在其初始化表里调用基类的构造函数。

48)类的const常量只能在初始化表里面初始化,不能在函数体内通过赋值初始化。

49)若不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省函数。

50)拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在的对象调用。

51)在编写派生类的赋值函数时,注意不要忘记对基类的数据成员的重新赋值。

52)C++的继承特性可以提高程序的可复用性。

53)若在逻辑上B是A的一种,并且A的所有功能和属性对于B而言都有意义,则运行B继承A的功能和属性。

54)const的用途:定义const常量;修饰函数的参数/返回值,甚至函数定义体。

55)被const修饰的东西都受到强制保护,可以预防意外的变动,能够提高程序的健壮性。

56)任何不会修改数据成员的函数都应该声明为const类型。

57)声明const成员函数时,const关键字只能放在函数声明的尾部。

58)程序效率评价角度可划分为:

时间效率从运行速度评价;

空间效率从程序占用内存或外存的状况评价;

全局效率从整个系统的角度上考虑;

局部效率从模块或函数的角度上考虑。

猜你喜欢

转载自blog.csdn.net/jiangsgyx/article/details/83103944