您的位置:首页 > 教育 > 锐评 > 个人公众号开发教程_做兼职的网站_seo搜索引擎优化工资_杭州百度快照

个人公众号开发教程_做兼职的网站_seo搜索引擎优化工资_杭州百度快照

2025/11/8 19:15:11 来源:https://blog.csdn.net/2402_87779153/article/details/146018660  浏览:    关键词:个人公众号开发教程_做兼职的网站_seo搜索引擎优化工资_杭州百度快照
个人公众号开发教程_做兼职的网站_seo搜索引擎优化工资_杭州百度快照

文章目录

  • C++初阶--基本语法讲解与类和对象
    • inline
    • nullptr
    • 结语

今天我们又不期而遇,给生活加点impetus!!开启今天的编程之路。
在这里插入图片描述
今天我们将C++入门语法讲解首尾,下章进入类和对象
作者:٩( ‘ω’ )و260
我的专栏:C++初阶,数据结构初阶,c语言,题海探骊
欢迎点赞,关注!!

C++初阶–基本语法讲解与类和对象

inline

我们首先来讲解结论:

1:C语⾔学习了宏,但是宏函数实现很复杂很容易出错的,C++设计了inline⽬的就是替代C的宏函数
宏函数的特点:没有调用函数的开销,预处理时直接替换即可,但是不能调试
内联函数的特点:不容易出错,方便调试

我们这里需要先理解:
宏的本质是替换。那么我们什么时候会用到宏呢?当我们频繁的调用函数时,就需要用宏
我们先来举例讲解宏函数的缺点:
我们先来写一个代表两数相加的宏:
这里有三种写法,请问哪一种是正确的呢?
在这里插入图片描述
这里我们来验证第一种:
在这里插入图片描述
我们来分析一下:宏的本质是替换,这里替换之后的代码为:

int ret=((1)+(2));;

注意后面其实是有一个空语句的,如果我们运用这个宏函数这样写:
在这里插入图片描述
就会报错,等价于:

if((1)+(2);)
{
}

这里最后其实是多了一个分号的,同理,运用该宏输出的话也会存在问题的。
我们再来看第二种,如果我们的代码是这样:
在这里插入图片描述
替换之后为:

(x&y+x|y);

但是我们上网查就能知道,+号的优先级是大于&和|的,就是先进行+号,但是一开始我是想最后再进行+号运算,所以这里的优先级不对。
我们再来看第三种,如果代码是这样的:
在这里插入图片描述
替换之后为:

(1)+(2)*5

我们发现这里的2先和5相乘再和1相加,仍然是优先级的错误。
虽然宏能够定义成宏常量和宏函数(宏常量 const/enum 宏函数inline),但是宏函数容易出错,而且,我们也无法调试
所以,C++中引用了inline(内联函数)。

2:⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内联函数就不需要建立栈帧了,就可以提高效率。

这一点的解释希望可以先去回顾一下函数栈帧的创建和销毁。
我们先来理解:函数的地址是什么?
当函数被定义的时候,在函数栈帧中会生成一系列的指令,这些指令各有各的地址,函数的地址就是该函数栈帧中第一个指令的地址
我们来举例验证一下:
在这里插入图片描述
因为Release版本不适合反汇编,记得调节为Debug模式,调试随后转到反汇编:
在这里插入图片描述
首先我们先打印了函数的地址,随后执行add(1,2)语句时,调用函数下方出现call指令,call的指令跳转到jump指令,随后又跳转到定义函数生成的一系列指令中的第一个指令。这里的验证是成立的。
这里我们如果给add函数加上inline,那会怎么样呢?
在这里插入图片描述

在这里插入图片描述

这里我们发现,在main函数中add函数的操作不再是call了,而是直接展开了
那么我们再来看,如果我们给add函数中再去添加几行代码,结果又会是怎样呢?
在这里插入图片描述
这时我们发现,反汇编中又有call了。没有展开。
所以我们可以认定:

call函数语句没有展开,反之就是展开了

那么这个展开能够省去函数调用的时间,那么是否就是一定没有缺陷呢?这里为什么有时候有call,有时候没call呢?
如果说我们此时需要频繁的去调用函数:
在这里插入图片描述
因为展开的话我每次需要call10000次才能进入函数,进入函数之后还会有待执行的10条指令,每次call都会多出10条指令,所以这里是乘,但是不展开的话我们只有10000次call和待处理的10行代码,指令就会少很多。注意这里不是算的执行的次数,而是生成的指令个数
所以;

inline的问题是会让编译的可执行程序变大,所以此时inline才没有展开。

3:inline展不展开由编译器决定,目的是防止程序员的错误而导致程序的内存增大。那种复杂的函数或者频繁调用的函数编译器一般不会展开inline函数,例如:递归函数。

4:vs编译器debug版本下⾯默认是不展开inline的,这样⽅便调试,debug版本想展开需要设置⼀下以下两个地方。

在这里插入图片描述

5:inline不建议声明和定义分离到两个文件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错

我们先来举一个简单的例子来说明一下:
我们现在Common.h文件中引入Swap交换函数,随后我们在test.cpp和Stack.cpp中引用Commom.h头文件:
在这里插入图片描述
运行的时候我们发现出现了这样一个报错:
在这里插入图片描述
从这里我们可以发现,我们的语法显示的是没有任何问题的。
我们这里其实是编译报错,在解释这个问题之前,我想请问读者:你能够准确说出全局变量的缺陷吗?
预处理,编译,汇编,链接后期我会出一期文章讲解,这里我们理解有这个过程就好:
在这里插入图片描述
首先程序预处理,将代码中的宏给替换掉,随后编译检查语法是否错误,随后生成二进制的指令,这三步骤完成之后,会生成对应的obj文件,链接会让这些obj文件相互联系,最终生成一个可执行文件exe。

在汇编完成的时候,对应的obj文件还会有一个符号表生成,未处理的函数会进入符号表,Stack.cpp中的Swap函数和Test.cpp中的Swap函数会进入符号表,链接时编译器寻找符号表中的内容,当发现两个符号表中都有Swap函数时,此时编译器就会报错重定义

那我们明白了报错原理之后,我们应该怎么去解决呢?
法1:我们给定义的函数加上static修饰
在这里插入图片描述

本质:函数加上static之后就会变成静态函数,编译器会在生成的 .obj 文件中直接处理这些函数的调用。因为静态函数是在编译的时候就已经解析好了
我们认为静态函数具有 内部链接属性静态函数的作用域仅限于定义它的文件。其他文件无法直接调用该函数。那么静态函数不会进入 全局符号表 ,因此其他文件无法通过符号表访问它它的符号仅在其所在文件内可见
法2:定义和声明分开写,我们在头文件中写声明,在源文件中写定义,本质是接着创建了一个符号表,Swap函数只有在新创建的符号表中存在。
在这里插入图片描述
此时链接的时候前两个符号表中都没有Swap函数,只有第三个符号表有,其中存储的是Swa函数的地址,就是第一个指令的地址

关于是否会进入符号表,可以那样理解:只有有定义的地方,才可能会进入符号表,只有有定义的地方,才会有地址,定义函数的时候才会生成一系列指令,函数声明只是一个承诺

我们明白了这个原理,我们再来看这个示例:
在这里插入图片描述
报错无法解析的外部指令,原因就是在obj文件的符号表中,并没有保存着f函数的地址,导致无法找到这个函数,那这个是什么原因导致的呢?
是因为内联函数会在函数调用的地方替换函数,导致函数的地址不在了,该函数无法寻得,call的时候需要地址才能call,替换时函数就没有地址了

总结链接的问题:
1:没定义
2:inline定义和声明分离(不在一个文件中了)

nullptr

NULL其实是一个宏,在传统C的头文件stddef.h中可以看到下面代码:
在这里插入图片描述
上述说明:在C++中,NULL其实就是整形0,即在预处理阶段会被替换成0,在c语言中,代表的是无类型指针(void*)的常量,可以理解为可以接收任何类型的0地址,这种定义方式会存在一些问题,我们来看下面这句代码:

#include"Commom.h"
#include<iostream>
using namespace std;
void f(int x)
{cout << "f(int x)" << endl;
}
void f(int* ptr)
{cout << "f(int* ptr)" << endl;
}//函数重载
int main()
{f(0);f(NULL);f((int*)NULL);return 0;
}

请问这三句函数调用的结果是什么?
在这里插入图片描述

第一句调用我们肯定是调用第一个,这是正确的,第二句调用NULL我们首先会看成指针,我们认为应该是调用第二个,但是实际上是调用第一个,第三局调用还给NULL强制类型转换,十分别扭。才能调用第二个函数。
这里我们引入了一个叫nullptr的关键字来初始化指针,同时也能够增强代码的可读性。

但我们传递nullptr的时候,就会调用第二个函数。

NULL与nullptr最大的区别:null本质上是整形,nullptr本质上是地址

结语

感谢大家认真阅读我的博客,不足之处欢迎与我交流,错误之处或不理解之处欢迎评论区留言。
时人不识凌云木,直待凌云始道高!!加油!!
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com