当前位置: 首页 > news >正文

C++入门(下)--《Hello C++ World!》(2)(C/C++)

文章目录

  • 前言
  • 引用
    • 临时变量的一个小知识点
  • 引用和指针的区别
  • 内联函数
    • 内联函数
    • 遗忘的补充:宏函数
  • 指针空值---nullptr
  • 作业部分

前言

这期会把上一期C++入门没有讲完的引用,内联函数跟nullptr给讲完,下期将会讲解类和对象
关于 C++的文章通通收录在了这个专栏里面:
在这里插入图片描述

引用

概念:引用是给已存在变量取了一个别名,它和它引用的变量共用同一块内存空间。

规则:

1.引用在定义时必须初始化

2.一个变量可以有多个引用

3.引用一旦引用一个实体,再不能引用其他实体

4.引用过程中,权限不可以扩大,只能平移和缩小(权限指的是eg:以后可以既读又改,现在只能读了)

使用场景:

1.作为函数的形参

1.做输出型参数–想里面改变,对应外面也改变的那种

2.减少拷贝,提高效率–对大对象(参数很多的那种,比如:一万个形参都用引用)或者深拷贝对象有用

2.作为函数的返回值

1.减少拷贝,提高效率–对大对象(参数很多的那种,比如:一万个形参都用引用)或者深拷贝对象有用(传值返回用拷贝,传引用返回不要拷贝)

2.修改返回值/获取返回值

 使用举例:
int a = 10;
int& ra = a;int* x = &a;
int*& p = x;引用一旦引用一个实体,再不能引用其他实体:举例:
int a = 10;
int& ra = a;
int b = 11;
ra = b;//这句话是改变ra的值,不是让ra成为b的引用一个变量可以有多个引用,举例:
int a =0;
int& b = a;
int& c= b;引用过程中,权限不可以扩大,只能平移和缩小,举例:(这个点属于常引用的)const int a = 0;int& b = a;//这个是不行的,扩大了int x = 0;
int& y = x;
const int& z = x;//这里是权限缩小
x++;//这里会间接导致z++,但是z不能直接自己++const int& m = 10;这样也是允许的
但是int& m =10;就不行
引用作函数返回值:
先举个例:
非引用:
int Count()
{int n = 0;n++;
return n;//这个的话是靠创建临时变量(变量占字节小的时候才是用寄存器)去过渡
}引用:
int& Count()
{int n = 0;n++;
return n;
}
int main()
{
int ret = Count();
}这样的话,分两种情况:
1.如果Count函数结束,栈帧销毁,没有清理栈帧的话,那么ret的结果侥幸是正确的2.如果Count函数结束,栈帧销毁,清理栈帧,那么ret的结果是随机值
(特别是Count用了之后还进行了其他操作去用栈帧)总结:引用做返回值时,出了函数作用域,对象不在了,就不能用引用返回,还在就可以用引用返回
eg:
int& Count()
{static int n = 0;n++;
return n;//这里返回的相当于是n的别名
}
int& SLAt(SeqList*ps,int pos)
{
return ps->a[pos];
}
易错点:
int& Count()
{int n = 0;n++;// ...return n;
}int main()
{int ret = Count();//这里的ret是n的拷贝,不是引用,要int& ret = Count();才是return 0;
}

临时变量的一个小知识点

编译器为了执行代码搞的大部分临时变量都具有常性

举例: double dd = 12.21;int& i = dd;//这时就会报错但是
double dd = 12.21;
int i1 = dd;
int& i = i1;//这就不会报错int func()
{static int x = 0;return x;
}
main函数里面int& ret = func();//这样就不行要const int& ret = func();//这样才行

常见情况:

1.发生类型转换时会产生临时变量来辅助,这时的就具有常性

2.传值引用返回值返回时也会产生临时变量,也有常性

3.隐式转换

(临时变量没有常性的情况以后才会提及)

引用和指针的区别

语法层面:

引用是不开空间,是对a取别名 指针是开空间,存储a的地址

从底层汇编指令实现的角度来看:引用是类似指针的方式实现的–也就是引用也会开空间

平时理解:引用的语法理解当不开空间,要是谈到底层的话,那就是会开空间

引用和指针的不同点:
1.引用概念上定义一个变量的别名,指针存储一个变量地址。
2.引用在定义时必须初始化,指针没有要求
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
4.没有NULL引用,但有NULL指针
5.在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
6.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7.有多级指针,但是没有多级引用
8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理(底层)
9.引用比指针使用起来相对更安全

内联函数

内联函数

概念:以inline修饰的函数叫做内联函数

作用:在编译器编译时,会在调用内联函数的地方把内联函数在那展开(不会像自定义函数一样是通过call搞得),这样可以避免函数调用建立栈帧的开销

适用范围:适用于短小并且频繁调用的函数。

原因:如果不频繁的话,用的效果不明显;函数比较长的话,在编译过程中的指令会非常长,导致可执行程序的占用内存会很大(现在编译器可以主动避免这个了)

inline对于编译器只是一个建议,最终是否成为inline,是由编译器自己决定的

编译器会ban掉的一些函数(不让他成为内联,让他就是普通的函数):

1.比较长的函数

2.大多数递归函数

注意:深度深的递归跟频繁调用的函数是有差别的,不能等同:深度深的递归eg:1000*999一直乘到1这样一下算下来的话会导致文件变得很大,频繁调用函数则不会

默认debug模式下,inline在编译过程中不会起作用,否则就不方便调试了

在release版本下才会起作用,但是release版本下又看不了编译,这个需要自己去设置(不同软件的设置方法不一样)

注意:inline不建议声明和定义分离(要在同一文件下),分离会导致链接错误–原因:inline被展开之后,定义就没有函数地址了,链接就找不到那个函数的地址,就会报错

内联函数展示:
inline f(int a)
{return a*10;
}//也就在前面加个inline就行了

遗忘的补充:宏函数

优点:不需要建立栈帧,提高调用效率

缺点:复杂,容易出错;可读性差;不能调试(因为预编译阶段进行了替换)

C++中替代宏函数的方法:内联函数

举例:
正确写法:#define f(x,y) ((x)+(y))
易错点:1.后面加了;号和return2.f(x,y)写成了f(int x, int y)  3.x和y没有加()以及大整体没有加括号--出错原因:万一是f(a|b,a&b)隐藏知识点:+比&和|的优先级高

指针空值—nullptr

在后续表示指针空值时建议最好使用nullptr。

跟用0或者NULL表示指针空值的区别:

void f(int)
{
}void f(int*)
{
}f(0);//会调用第一个--默认情况下0被看作是一个整形常量,不行的话才是(void*)0
f(NULL);
//会调用第一个--NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量(具体看编译器是哪种)
f(nullptr);//会调用第二个

补充知识:像这种形参只给了类型的,没有给名字的也行,如果函数里面没有使用这个形参的话

作业部分

引用传值,指针传地址(X)
原因:引用表面好像是传值,其本质也是传地址删除空指针是无害的,但是不能删除引用(对)
原因:空指针没有任何指向,删除无害,引用是别名,删除引用就删除真实对象
关于c++的inline关键字,以下说法正确的是(BC) 
A.使用inline关键字的函数会被编译器在调用处展开
B.头文件中可以包含inline函数的声明
C.可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数
D.递归函数也都可以成为inline函数A:要看编译器有没有把他处理成内联函数
B:如果头文件里有内联函数的声明和定义的话就行

相关文章:

  • 金仓数据库征文-金仓KES数据同步优化实践:逻辑解码与增量同步
  • 深度 |提“智”向新,奔向未来——当前机器人产业观察
  • 实时操作系统:航空电子系统的安全基石还是创新枷锁?
  • Vue事件总线(EventBus)使用指南:详细解析与实战应用 父子组件传值
  • 计算机体系架构-----设计模式:状态模式(从程序员加班问题切入)
  • 顺丰科技:从 Presto 到 Doris 湖仓构架升级,提速 3 倍,降本 48%
  • GoWeb开发
  • R1-Searcher:用强化学习解锁大语言模型检索新能力!
  • 【ArcGIS技巧】用地块生成界址点去重、顺时针编号挂接DKBM属性
  • [python] 函数基础
  • B站pwn教程笔记-8
  • 【微信小程序开发】从0开始的一点点小记录
  • 电厂参与全球能源效率排名的方法
  • Python实现中文数字与阿拉伯数字映射生成器(支持0-9999)
  • 《开源先锋Apache软件基金会:历史沿革、顶级项目与行业影响》
  • Android单例模式知识总结
  • 使用迁移学习的自动驾驶汽车信息物理系统安全策略
  • Java数据结构——Queue
  • LeetCode热题100--54.螺旋矩阵--中等
  • 商业中的人工智能 (AI) 是什么?
  • 【社论】职业上新,勇于“尝新”
  • 丹麦召见美外交官,强调“不能容忍”美在格陵兰岛间谍活动
  • 眉山“笑气”迷局:草莓熊瓶背后的隐秘与危机
  • 融创中国:今年前4个月销售额约112亿元
  • 巴基斯坦称约50名印度士兵在克什米尔实控线丧生
  • 见微知沪|优化营商环境,上海为何要当“细节控”自我加压?