22、隐式类型转换
首先,对于内置类型,低精度的变量给高精度变量赋值会发生隐式类型转换,其次,对于只存在单个参数的构造的对象构造来说,函数调用可以直接使用该参数传入,编译器会自动调用其构造函数生成临时对象。
23、C++成员变量的初始化顺序
(1)初始化顺序:
基类的静态变量或者全局变量-->派生类的静态变量或者全局变量-->基类的成员变量-->派生类的成员
(2)原因:
静态变量和全局变量都是存放在公共的内存区,不需要实例化一个对象就已经存在了。
先初始化基类的静态静态变量或者全局变量,再到派生类,当所有的静态变量和全局变量都已经初始化完毕后,main函数会被调用,如果某个类的构造函数被执行,那么也是先初始化基类的成员变量再初始化成员变量。
(3)注意:
Ⅰ:成员变量在使用初始化列表初始化的时候,与初始化成员列表的顺序无关,只与定义的成员变量的顺序有关。因为成员变量的初始化是根据变量在内存中次序有关,而内存中的排列顺序在编译器就根据变量的定义决定了。
Ⅱ:类成员在定义时不能初始化
Ⅲ:类中const成员常量必须在构造函数初始列表中初始化
Ⅳ:类中static成员变量必须在类外初始化(防止实例化对象的时候重新给static赋值,如果是const static就可以在类内初始化)
24、new/delete 与 malloc/free的区别是什么
首先,new/delete是C++的关键字,而malloc/free是C语言的库函数。后者使用必须指明申请内存空间的大小,对于类类型的对象,后者不会调用构造函数和析构函数。
25、几种new的用法
(1)new operator即new操作符,不能被重载,调用的时候,先申请内存,再调用构造函数,这是常用的调用方式。
(2)operator new操作符,能够被重载,单纯申请内存,相当于C语言中的malloc, 如果重载了operator new操作符,又需要调用原来的函数,那么需要在操作符前面加上::(即 ::operator new),重载该操作符通常是为了实现不同的内存分配方式。
(3)placement new操作符,仅仅返回已经申请好内存的指针,它通常应用在对效率要求高的场景下,提前申请好内存,能够节省申请内存过程中耗费的时间。
详细可以看C++new的几种用法详解
26、#define 和const有什么区别?
(1)编译器处理方式不同:#define宏是在预处理阶段展开,而const常量是在编译阶段使用
(2)类型与安全检查不同:#define宏没有类型,不做任何类型检查,仅仅是代码展开,而const常量有具体类型,编译阶段会执行类型检查
(3)存储方式不同:#define仅仅是在多个地方进行字符串替换,不会分配内存,存储在程序的代码段中,而const常量会分配内存,存储在程序的数据段中
(4)定义域不同:#define宏不受定义域限制,而const常量只在定义域内有效
27、对于一个频繁使用但是短小的函数应该使用什么实现?有什么优缺点?
应该使用inline内联函数,编译器会将inline内联函数内的代码替换到函数被调用的地方。
优点:
(1)内联函数在调用的地方进行代码展开,省去了函数调用的时间,提高程序运行的效率
(2)相对于宏函数,编译器会进行语法安全检查或者数据类型转换,使用更加安全
缺点:
(1)代码膨胀,产生更多的开销
(2)如果修改内联函数,那么所有调用该函数的代码文件都需要重新编译
(3)内联函数只是建议,是否内联需要编译器决定,所以实际并不可控
28、悬挂指针与野指针有什么区别?
(1)悬挂指针:当指针所指向的对象被释放,但是该指针仍旧指向被释放的内存地址,该指针称为悬挂指针
(2)野指针:未初始化的指针被称为野指针