目录
💕1.宏函数讲解
💕2.内联函数存在的意义是什么
💕3.如何书写内联函数
💕4.内联函数的意义与作用
💕5.内联函数注意事项
💕6.内联函数的展开条件 (如何设置)
💕7.关键字auto
💕8.关键字auto需要注意的点
💕9.auto遍历数组
💕10.C++中的NULL更迭
(最新更新时间——2025.1.10)
二十七步天注定
逆流河上任我行
💕1.宏函数讲解
#define ADD(a, b) ((a) + (b))int main() {int ret = ADD(1, 2);cout << ADD(1, 2) << endl;int x = 1, y = 2;ADD(x & y, x | y); // -> (x&y+x|y)return 0; }
思考->:为什么宏函数的 a 与 b 要各自有一个括号,这是因为 a 与 b实行的是a+b,而在实行a+b时,正如我们在main函数中写到的,ADD(x&y,x|y),因为&与|操作符的优先级小于+,所以如果不加括号,就会变成x&y+x|y,这里就会先算成y+x,然后算x&(y+x),最后算(x&(y+x))|y
💕2.内联函数存在的意义是什么
内联函数存在的意义
- 内联函数最初的目的:代替部分 #define 宏定义;
- 使用内联函数替代普通函数的目的:提高程序的运行效率;
💕3.如何书写内联函数
内联函数的书写方法->:
inline int Add(int a, int b) {int ret = a + b;return ret; }int main() {int c1 = Add(1, 2);cout << c1 << endl;return 0; }
我们可以发现,只要在我们之前所写函数的样例前,加上关键字 "inline" 就属于内联函数
那么,内联函数的作用是什么?
💕4.内联函数的意义与作用
内联函数,相当于把一整个函数展开,相当于将代码全部放在main函数内,这样省去了参数压栈、生成汇编语言的CALL调用、 返回参数、执行return等过程,从而提高了速度
我们举一个简单的例子,如下->:
inline int Add(int a, int b) {int ret = a + b;return ret; }int main() {int c1 = Add(1, 2);cout << c1 << endl;return 0; }
在这样的代码中,我们使用内联函数,省去了参数的空间开辟,省去了返回值的执行,更快地提高了运行的空间
但是这种情况并不是一直的,我们再举一个例子,如果说一个函数里有100行代码,而程序需要执行10000次,那么使用内联函数展开和不展开的区别是什么?
我们思考下,如果我们不展开的话,每一次执行一次函数,一共执行了10000次,每一次都会创建栈佂并进行销毁
而如果展开呢,每展开一次main函数内部会执行100行代码,那么展开10000次一共就执行了100W行代码,开辟内存空间会相当巨大,这就会导致同一个游戏,不展开时更新的内存极小,而展开后更新的内存极大
但是好在C++中避免了这种情况,在C++中,为了防止各位乱搞,C++祖师爷会在函数内部特别长的时候,即使你使用内联函数展开,也不会让你展开,这是一个极其好的点,示例如下->:
先来一段函数代码极长的情况->:
再由汇编码可见,即使我们使用了内联函数展开,依旧不会展开,因为函数内的代码太长了
(蓝色部分汇编码为调用函数——未展开)
接下来是函数内部代码少的时候->:
由汇编码可见,使用内联函数展开确实展开了函数在main函数内,并没有调用函数
💕5.内联函数注意事项
inline 不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。
我们可以从汇编码知道,调用函数是因为能找到函数的地址,而使用inline展开后,函数就不会开辟空间也就是不会有地址,那么没有地址的话自然就调用不了函数,这就导致在.h与.c文件中使用内联函数会出现一些问题,请看代码->:
我们发现,系统会报错,而这正是因为找不到main函数中找不到函数的地址,因为你展开到了abc.cpp中,因此函数的地址消失了,而main.cpp中就找不到了函数的地址,也就会编译错误,因此,在多文件时,我们都会将内联函数的声明和定义都写在头文件中代码如下->:
abc.cpp中就不需要重复写了
💕6.内联函数的展开条件 (如何设置)
首先,内联函数只有在Release时才会实现,而在Debug时并不会实现,但是Release的情况下汇编码极其冗长复杂,那么有没有一种方法可以在Debug时也可以展开呢?
答案是有的,接下来按照我的操作->:
💕7.关键字auto
关键字auto会自动识别变量的类型,具体代码实例如下->:
int main() {auto a = 2;auto b = 2.2;auto c = 3.f;auto p = &a;cout << typeid(a).name() << endl;//打印intcout << typeid(b).name() << endl;//打印doublecout << typeid(c).name() << endl;//打印floatcout << typeid(p).name() << endl;//打印int* }
这里使用到了typeid().name,它会自动识别出变量的类型
💕8.关键字auto需要注意的点
在使用auto时,我们需要注意几点,如下->:
在auto后面时,如果我们什么都没加,那它就会自动识别为什么类型,但如果我们加了一些东西,那么我们传入的类型就必须是与之对应的
💕9.auto遍历数组
在C++中,我们想要遍历数组,可以使用除了for别的方法,那就是auto,具体代码如下->:
int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 };// 自动取数组arr中,赋值给k// 自动++,自动判断结束for (auto& k : arr){cout << k << " ";} }
这里的意思是指,自动取数组arr,将它赋值给它的别名-k,再自动++,并自动判断是否结束
💕10.C++中的NULL更迭
先看图片->:
在C语言中,我们通常指NULL就是空指针,但实际上,在C语言中的宏,NULL被定义为0,这也就导致了一个坑,当我们传参为NULL时,实际上会调用void f(int i)这种函数,直到C++中,这个坑被填平
在C++中,空指针被重新命名为 nullpter 因此在以后的C++中,空指针都会用nullptr表示,防止混淆