建设银行网站是多少钱,做生蚝的网站,wordpress媒体库全选,安阳十大著名景点目录一. 前言二. 函数重载1. 概念2.函数名修饰规则三 .引用#xff08;#xff09;1. 概念2. 引用特性3.应用1.做参数2. 做返回值3. 传值、传引用效率比较4.引用和指针的区别四 . 结语一. 前言
小伙伴们大家好#xff0c;今天我们继续学习c入门知识#xff0c;今天的…
目录一. 前言二. 函数重载1. 概念2.函数名修饰规则三 .引用1. 概念2. 引用特性3.应用1.做参数2. 做返回值3. 传值、传引用效率比较4.引用和指针的区别四 . 结语一. 前言
小伙伴们大家好今天我们继续学习c入门知识今天的内容主要是
二. 函数重载
1. 概念 函数重载是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这 些同名函数的形参列表(参数个数 或 类型 或类型顺序)不同常用来处理实现功能类似数据类型 不同的问题 可以理解为一词多义比如一句话**“谁也赢不了”**分别用在国乒乓队和国足的身上就是两种截然不同的意思大家细品。
int Add(int left, int right)
{
cout int Add(int left, int right) endl;
return left right;
}double Add(double left, double right)
{
cout double Add(double left, double right) endl;
return left right;
}然而c语言不支持函数重载上述代码运行会直接报错。 三种重载方式 1· 参数类型不同 2、参数个数不同 3、参数类型顺序不同 //参数类型不同
int Add(int left, int right)
{
cout int Add(int left, int right) endl;
return left right;
}
double Add(double left, double right)
{
cout double Add(double left, double right) endl;
return left right;
}// 2、参数个数不同
void f()
{
cout f() endl;
}
void f(int a)
{
cout f(int a) endl;
}// 3、参数类型顺序不同
void f(int a, char b)
{
cout f(int a,char b) endl;
}
void f(char b, int a)
{
cout f(char b, int a) endl;
}2.函数名修饰规则
由之前的知识我们知道函数调用需要建立栈帧那么编译器是如何精确找到这些同名函数的地址呢 c语言是根据函数名寻找函数如果函数名相同就会起冲突。 而c通过函数名重载对函数的地址进行修饰 windows下的函数修饰名规则太复杂所以我们转到Linux上对其讲解 Linux下修饰规则格式_ Z 函数名称长度 函数名 类型首字母 代码段 1 #includestdio.h2 3 void add(int a,int b)4 { 5 } 6 7 int main(){8 9 return 0;10 }
进行编译形成可执行文件后还需借助objdump -S exeName 查看修饰规则 结果为 我们发现c语言是直接根据函数名查找对应函数
改图为c编译后的代码段
所以说 对于相同名字的函数函数重载就根据参数的类型顺序个数以这些为基准来区别不同的函数 但是不同返回值的函数不能构造函数重载 对于返回值不同的其他都相同的函数来说在函数调用时无法进行区分返回值分不清调用哪个函数不仅仅是因为函数返回值不在修饰规则内。 三 .引用
1. 概念 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间它和它引用的变量共用同一块内存空间 通俗来说就是取外号 你很瘦他人给你取了个外号叫“竹竿”他的意思就是”竹竿“也代表了你
定义 类型 引用变量名(对象名) 引用实体 实现如下
int a 10;
int b a;b 20;
cout a endl;可以看出a和b共用一个地址且b为int 类。 注意引用类型必须和引用实体是同种类型的 2. 引用特性 引用在定义时必须初始化一个变量可以有多个引用引用一旦引用一个实体再不能引用其他实体 前俩条很好理解最后一个是指当引用初始化之后就不能改变引用的指向了 可以看出b的值变成了20a的值也改变成为了20但b的地址没有改变说明了 引用一旦引用一个实体再不能引用其他实体
3.应用
1.做参数
还记得c语言中的交换函数怎么实现的吗
void swap(int *a ,int *b)
{int tmp*a;*a*b;*btmp;
}是不是感觉十分别扭既要传指针又要进行解引用 现在我们可以用引用来进行简化
void swap(int a ,int b)
{int tmpa;ab;btmp;
}传递过来的都是实参的别名可以直接修改无需解引用
2. 做返回值
看如下代码
int add(int a, int b)
{int c a b;return c;
}int main()
{int ret add(1, 2);cout ret endl;return 0;
}我们在调用函数时会建立函数栈帧对于传值返回如上述代码的add函数在函数调用完成后函数栈帧销毁c变量也会销毁所以传会的并不是变量c而是c的一份拷贝是一个临时变量。 但是临时变量在哪 如果 c 比较小(4/8 byte)一般是寄存器充当临时变量。 如果 c 比较大临时变量放在调用 add 函数的栈帧中。 如果定义一个静态的变量呢static修饰的变量储存于静态区不受函数栈帧的影响那么返回他会不会进行拷贝呢答案是会的。 那么就会产生浪费如何进行规s避呢
我们试一试传引用返回
int add(int a, int b)
{int c a b;return c;
}int main() {int ret add(1, 2);cout ret endl;add(10, 20);cout ret endl;return 0;
}运行结果 可知ret为int类在第一次调用add函数栈帧销毁后ret任可以访问当初函数c的地址所以在第二此调用add后ret的值被改为30 也就是非法访问。
引用返回有一个原则 如果函数返回时出了函数作用域如果返回对象还在(还没还给系统)则可以使用引用返回如果已经还给系统了则必须使用传值返回。 3. 传值、传引用效率比较 以值作为参数或者返回值类型在传参和返回期间函数不会直接传递实参或者将变量本身直接返回而是传递实参或者返回变量的一份临时的拷贝因此用值作为参数或者返回值类型效率是非常低下的尤其是当参数或者返回值类型非常大时效率就更低 通过上述代码的比较发现传值和指针在作为传参以及返回值类型上效率相差很大。
4.引用和指针的区别
int main()
{
//引用
int a 10;
int ra a;
ra 20;
//指针
int* pa a;
*pa 20;
return 0;
}我们看看反汇编码 发现指针和引用的底层逻辑是一样的。 所以 从语法概念上来说引用是没有开辟空间的而指针是开辟了空间的 但是 从反汇编代码上来看引用其实是开空间的并且实现方式和指针一样引用其实也是用指针实现的。
引用和指针的不同点:
引用概念上定义一个变量的别名指针存储一个变量地址。引用在定义时必须初始化指针没有要求引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型实体没有NULL引用但有NULL指针在sizeof中含义不同引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个字节)引用自加即引用的实体增加1指针自加即指针向后偏移一个类型的大小访问实体方式不同指针需要显式解引用引用编译器自己处理引用比指针使用起来相对更安全
四 . 结语
大家好我是展轩 本次博客学习就到这里如果觉得有帮助的话记得 一键三连哦ヾ(≧▽≦*)o。