《C和C++程序员面试秘笈》第2章 预处理、const、static与sizeof

1. 预处理的使用

#ifdef XXX
#endif

2. #define

1、三目运算符( ? : ),能产生比if-else更优化的代码,并且书写上更加简洁明了
2、用#define定义的宏,如果是替换为数值类型,需要把参数括起来;如果只是简单的文本替换,如果不注意,使用时很容易引起歧义

3. #define 宏定义的使用

宏定义展开是在预处理时期,也就是在编译之前
如果参数需要加括号,加括号时,要加齐全

4. 宏参数的连接

1、使用#把宏参数变为一个字符串
   #define STR(s) #s
   STR(s)定义的是一个参数s表示的字符串
   当调用时,如:STR(vck),实际表示就是字符串“vck”
2、使用##把两个宏参数贴合在一起
   #define CONS(a,b) (int)(a##e##b)
   CONS(a,b)定义的是一个将参数a b按aeb连接起来的一个整型值
   当调用时,如:CONS(2,3),实际表示的就是整型值2e3,也就是十进制数2000

5.略
6.略

7. const的使用

常量指针  const修饰的是指针指向的内容,指针指向的内容为常量,不能改,指针指向可以改 
         const int* PointerToInt
指针常量  const修饰的是指针,指针指向不能更改,指针指向的内容可以改
         int* const PointerToInt

8. const与#define的特点与区别

#define 只是用来做文本替换的
const常量 有数据类型,编译器可以对其进行类型安全检查

9. C++中const有什么作用

1const定义常量,编译器可以对const常量进行数据静态类型安全检查
2const修饰函数形参,参数为用户自定义类型或者抽象数据类型时,“值传递”改为“const & 传递”,可以提高效率
3const修饰函数的返回值
4const修饰类的成员函数(函数的()后加const),任何不会修改数据成员的成员函数都应用const修饰

10. static有什么作用

1、全局的static变量(静态变量),可以被本文件内所有函数访问,不能被其他文件访问,被限制为一个本地的全局变量
2、局部的static变量(函数体内),只能被本函数调用

11. static全局变量与普通全局变量有什么区别

1static全局变量:只初始化一次;只能在定义该变量的源文件内使用
	普通全局变量:可被一个程序的各个源文件使用
2static局部变量:只初始化一次,下一次依据上一次的结果值
3static函数:在内存中只存在一份
	普通函数:在每个被调用中维持一份复制品

12. C++中类的静态成员

类的静态成员、静态方法不属于类的实例,而是属于类本身并在类的实例间共享;不占用类实例的空间(其中静态成员变量存在于静态存储区)。
在调用它们时应该用"类名::静态方法()"

13. sizeof计算普通变量所占空间大小

数组和指针的sizeof运算有细微的区别
	对“数组变量(数组名)sizeof运算得到的是数组占内存的总大小
	如果“数组变量(数组名)”被传入函数中做sizeof运算,则和指针的sizeof运算没有区别
	对于指针,无论何种类型的指针,其大小都是固定的;在321位WinNT平台下都是4

14. sizeof计算 类对象 / 结构体变量 所占空间大小(字节对齐)

C++的内存对齐方式取决于
	1、取 编译器默认对齐大小 与 对象中最大成员  两者中较小的一个
	2、现阶段,编译器默认对齐大小为8
	
一般而言满足3个准则
	1、结构体变量的首地址,能被其成员中最宽基本类型大小所整除
	2、结构体中每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍;
	   如有需要,编译器会在成员之间加上填充字节(internal adding)
	3、结构体的总大小为结构体成员中最宽基本类型大小的整数倍;
	   如有需要,编译器会在最末一个成员之后加上填充自(trailing padding)

15. sizeof计算含有虚函数的类对象的空间大小

普通函数不占用类对象的内存
类中只要有虚函数,就会占用一个指针大小的内存
	原因是:系统多用了一个指针维护这个类的虚函数表
	并且注意,类中无论含有几个虚函数,都不会影响类的大小(因为只有一个虚函数指针,这个虚函数指针用来维护虚函数表)

16. sizeof计算"虚继承"的类对象的空间大小

虚继承时,编译器会为子类安插一个指向父类的指针
	一个虚继承,子类里有一个指向父类的指针
	多个虚继承,子类里有多个指向父类的指针(一一对应)

17. sizeof与strlen的区别

sizeof
	是操作符--计算所占内存空间大小 "\0"计算在内
	结果类型为size_t,即unsigned int类型
	类型做参数时,必须加“();变量名做参数时,可以不加“()”
	数组名直接传递给sizeof不退化为指针
	sizeof()可以用来定义数组维数
	
	sizeof计算字符串数组时,结果为字符串数组实际占用的字节数,"\0"计算在内
	
strlen
	是函数--计算字符串的长度 "\0"不计算在内
	只能用“char *”做参数,且必须以“\0”结尾
	数组名直接传递给strlen退化为指针
	
	strlen计算字符串数组时,结果为字符串实际占用的字节数,"\0"不计算在内

	如果要计算指针指向的字符串的长度,则一定要使用strlen
		char * ss = "0123456789";
		int a = sizeof(ss);//4
		int b = strlen(ss);//10

18. sizeof有哪些用途

1、查看某个类型的对象在内存中所占的字节数
2、动态分配对象的内存时,让系统知道要分配多少字节
3、涉及操作数字节大小时,用sizeof代替常量计算

19. 使用strlen()函数代替sizeof计算字符串长度

1sizeof()不能计算字符串长度
2strlen()函数用于计算字符串长度

20. sizeof计算联合体的大小

unionstructclass内存对齐方式相同
union的大小
	1、成员中占用空间最大的一个成员的大小
	2、如果需要,进行内存对齐

#pragma pack(x)可以改变编译器的默认对齐大小

C++的内存对齐方式取决于
	1、取 编译器默认对齐大小 与 对象中最大成员  两者中较小的一个
	2、现阶段,编译器默认对齐大小为8

21. #pragma pack的作用

#pragma pack(x)可以改变编译器的默认对齐大小

22. 为什么要引入内联函数(inline)

宏函数
	仅仅只是做预处理器符号表中的简单替换
		不能进行参数有效性的检测
		不能享受C++编译器严格类型检查的好处
		返回值不能被强制转换为合适类型
		因此,它的使用就存在着一些列的隐患和局限性
C++中引入了类即类的访问控制
	设计类中的保护成员或私有成员时,就无法使用这种宏函数
	因为无法将this指针放在合适的位置
inline推出的目的
	正是为了取代宏函数
	消除了它的缺点,同时又很好的继承了它的优点

23. 为什么inline能很好的取代宏函数

inline定义的内联函数
	1、函数的代码被放入符号表中,在使用时直接进行替换(像宏一样展开),没有了调用的开销,效率也很高
	2、是一个真正的函数,编译器在调用一个内联函数时,首先会检查参数的类型,然后进行一些列的相关检查
	3、可以作为某个类的成员函数,这样就可以使用类的保护成员及私有成员

24. 内联函数的使用场合

1inline函数可以完全替代宏函数
2、类中的数据成员,一般被定义为私有的或者保护的
  把读写数据成员的成员函数定义为inline函数,将会获得比较好的效率
3、类中
  成员函数的定义被放在类声明中-->自动建议编译器把它便以为成inline函数
  定义被放在类声明之外,那么要加上inline关键字,才会建议编译器把它编译为内联函数

25. 为什么不把所有的函数都定义为内联函数

内联函数是以代码膨胀(复制)为代价的,仅仅省去了函数调用的开销;
如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收获会很少
另外,内联函数的使用将使程序的总代码量增大,消耗更多的内存空间

以下情况不建议使用内联函数
	1、函数体代码较长,使用内联函数将导致内存消耗代价高
	2、函数体内出现循环,执行函数体内代码的时间要比函数调用的开销大
	3、类的构造函数和析构函数容易让人误解成使用内联更有效。
	  要当心构造函数和析构函数可能会隐藏一些行为,比如“偷偷地”执行了基类或成员对象的构造函数和析构函数
	  
所以不要随便地将构造函数和析构函数的定义体放在类声明中!

一个好的编译器将根据函数的定义体,自动取消不值得的内联(这说明了inline不应该出现在函数的声明中)

26. 内联函数和宏定义的区别

1、内联函数在编译时展开,宏在预编译时展开
2、在编译时,内联函数可以直接被镶嵌到目标代码中,而宏只是一个简单的文本替换
3、内联函数可以完成诸如类型检测、语句是否正确等编译功能,宏函数就不具备这样的功能
3、宏函数不是函数,inline函数是函数
4、宏函数在定义时要小心处理宏参数(一般情况是把参数用括号括起来),否则容易出现二义性。而内联函数定义时不会出现二义性
发布了12 篇原创文章 · 获赞 10 · 访问量 7170

猜你喜欢

转载自blog.csdn.net/liangwenhao1108/article/details/104429852