内联函数
什么是内联函数?
使用inline修饰的函数叫做内敛函数,在编译时C++编译器会在调用内联函数的位置展开,所以没有函数压栈的开销,因此内敛函数提高了程序运行的效率
特性:
1.inline是一种以空间换时间的做法,省去调用函数开销,所以代码很长或者有循环/递归的函数不适合使用内联函数
2.inline对于编译器来说只是一个建议,编译器会自动优化。如果定义为inline的函数体内有循环/递归,编译器优化时会忽略内联函数
3.inline不建议将声明和定义分离,分离会导致链接错误,因为inline展开的话,无法找到函数地址,链接也找不到
宏
宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1.常量定义 换用const
2.函数定义 换用内联函数 inline
3.enum
结构体内存对齐
结构体内存对齐规则
1.第一个成员在结构体偏移量为0的地址处
2.其它成员变量要对齐到某个数字(对齐数)的整数倍的地址处
注意:对齐数=编译器默认的一个对齐数与该成员变量的较小值(VS中默认对齐数为8)
3.结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
4.如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍数处,结构体的整数大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
面试题:
1.为什么进行内存对齐?
内存对齐大大提高了cpu的读取速率。
1.并非所有硬件平台都可以访问任何地址上的任何数据,有些硬件平台也只能访问某些特定地址处某些特定类型的数据。
2.内存对齐的CPU只需要读取一次,没有内存对齐,CPU则需要读取两次。
2. 如何让结构体按照指定的对齐参数进行对齐?
设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数
3. 如何知道结构体中某个成员相对于结构体起始位置的偏移量?
可以使用这个#define offsetof(s,a) (size_t) (((s*)0)->a),这个用法就是我们告诉编译器有一个指针指向结构体s,而它的值是0,然后我们取结构体中的a,a的地址就是a的偏移量了
初始化列表
以一个冒号开始,然后以一个逗号分隔数据成员列表,每个成员变量后面跟着放初始值或表达式(构造函数体内的语句只能将其称做赋初值,不能称做初始化)
class Date
{
public:
Date(int year, int month, int day)
: _year(year) //括号中为初始值或表达式
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
注意:
1.每个成员变量只能在初始化列表中出现一次(即只能初始化一次)
2.当类中包含以下成员时,必须放在初始化列表位置进行初始化
引用成员变量,const成员变量,自定义类型成员变量(该类没有默认构造函数)
3.尽量使用初始化列表初始化,对于自定义类型,会优先使用初始化列表初始化
4.成员变量在类中的声明次序就是在初始化列表中的初始化顺序与其在初始化列表中的先后次序无关
函数入参压栈的顺序为什么是从左到右?
- 因为C语言支持可变参数,所以C语言函数参数入栈顺序为从右至左。C方式参数入栈顺序(从右至左)的好处是可以动态变化参数的个数 。函数最左边确定的参数在栈上的位置必须是确定的,否则意味着已经确定的参数是 不能定位和找到的,这样是无法保证函数正确执行的。衡量参数在栈上的位置,就是离开确切的 函数调用点(call f)有多远。
- 在《c和指针》中已经说明了从右向左压栈的原因,这样可以保证生成汇编语言时这些参数相对于BP指向的栈位置的偏移量是固定的,因为程序员有时为函数传递的参数会或多或或少,如果从左向右压栈,则从BP指向的位置到参数的偏移量就会根据用户传入的参数数量而发生改变,这时编译器的识别难度就会大大增加,因此才会从右向左压栈。
hash_map与map的区别
1.构造函数
- hash_map需要hash函数,等于函数
- map只需要比较函数
2.存储结构 - hash_map使用hash_table存储,查找时间为O(1)
- map一般采用红黑树实现,查找时间复杂度为log(n)
3.类型不同 - hash_map是一个类,map是一个接口
hash_map与map的使用场景
三个因素:查找速度,数据量,内存使用
- hash_map因为是用hash_table实现的,而hash_table是以空间换时间的,所以hash_map的内存消耗比较大,所以一般情况下,如果数据比较大,那么使用hash_map查找效率比较高(但是内存消耗会比较大)
- 虽然hash_map的查找时间复杂度为常数O(1),比map的查找时间复杂度要低,但是hash_map的hash函数和哈希冲突都要耗费时间
所以还是要看使用场景,不同的使用场景去使用最优的结构