【C->Cpp】由C迈向Cpp(3)


正文开始:

目录

(一)函数重载

 (1)函数重载

(2)函数重载实现原理

(二) 引用

(1)引用

(2)语法

         i ,别名:

        ii,传参:

        iii,返回值:

        iv,修改外部变量:

        v,避免空指针:


(一)函数重载

 (1)函数重载

        C语言不允许出现多个同名函数,而C++支持出现同名函数,这需要通过函数重载实现。 

        函数重载是指在一个类中,有多个同名的函数,但它们的参数列表不同。在C++中,函数重载可以通过函数名相同但参数列表不同来实现,参数列表不同可以包括参数类型、参数个数或者参数顺序等。当调用函数时,编译器会根据参数的类型或个数来自动选择合适的函数进行调用。

(2)函数重载实现原理

        在Linux下,C++函数重载的实现原理是使用了一种叫做"名称修饰"(Name Mangling)的技术。当C++源代码被编译成目标文件时,编译器会对函数的名称进行修饰,以区分不同的重载函数。

        名称修饰的过程是由编译器自动完成的,它将根据函数的参数类型、参数个数和参数顺序等信息生成一个唯一的符号名。这样,在目标文件中就能够通过不同的符号名来区分不同的重载函数。

(下面一linux的g++为例)

linux下的g++函数在修饰后变成:{   _Z + 函数名长度 + 函数名 + 类型首字母   }

 

//实例如下
Add(int,int)       ->   call     _Z3Addii
Add(double,double) ->   call     _Z3Adddd
//只要类型不同,类型顺序不同,类型个数不同,都可以让修饰后函数名不同,
//编译器可以区分不同的函数名,这样就构成了重载

        编译同一个文件,对于文件中的同一个函数,用gcc和g++编译出来的函数名称是不同的(符合上面规则):

用gcc编译的函数func1函数:

用g++编译的函数func1函数:

函数重载的作用主要有以下几点:

  1. 提高代码的复用性:通过函数重载,可以在一个类中定义多个功能相似的函数,避免了重复编写代码的问题。
  2. 提高程序的可读性:使用函数重载可以让程序更加直观清晰,减少了函数命名的复杂性。
  3. 增强了函数的灵活性:通过函数重载可以根据不同的参数选择不同的实现方式,从而提供了更多的选择。

        需要注意以下几点:

  • 重载函数的返回类型不可以作为重载的条件,只有参数列表不同才能作为重载的条件。
  • 重载函数的参数列表必须不同,参数个数不同或者参数类型不同都可以作为重载的条件。
  • 重载函数可以有不同的访问修饰符,比如一个是私有的,一个是公有的。

 

        需要注意的是,C++规定了可以函数重载,但是具体实现的名称修饰规则是由编译器决定的,不同的编译器可能会有不同的修饰规则。

(二) 引用

(1)引用

        引用不是新定义一个变量,而是给已存在的变量取了一个别名, 编译器不会为引用变量开辟内存空间,它和它引用的变量共同用一块内存空间

 

(2)语法

         i ,别名:

        引用提供了一个变量的别名,可以通过引用来访问已经存在的变量。这使得代码更加清晰和易读,同时也让函数传参更加方便,避免了拷贝大量数据的开销。

基本使用:

int i = 0;
int& j = i;//给i取别名j,j是i的别名

        j与i共用同一块内存地址;

        对i与对j的运算是等同的,j++后 i = 1 (其实就是i++ 后 i = 1); 

(引用类型必须和引用实体是同种类型的)

引用的特性:

        引用在定义时必须初始化;

        一个变量可以有多个引用;

 可以对别名取别名(套娃)对别名取别名,其实就是对原变量取别名,原变量与他的别名的地位是等同的(一个空间的名字可以是 “ i ”也可以是 “ j ” );

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

        引用需要与创建变量区分:

int i = 0; 
int j = i;//创建一个变量j初始化为0

        ii,传参:

        引用作为函数参数,可以将参数按引用传递,而不是按值传递。这样可以避免参数的拷贝,提高函数的执行效率,并且可以在函数内部修改参数的值(也就相当于传址),使得函数能够对传入的参数进行修改(同时也更好理解)。

 

//形参直接用实参的别名接收,便于直接对实参操作
void swap(int& r1,int& r2)
{int tem = r1;r1 = r2;r2 = tem;
}
int main()
{int a = 1,b = 2;swap(a,b);//不用再传地址,更好理解return 0;
}

 

        iii,返回值:

        函数可以返回引用类型,这样可以避免拷贝对象的开销,同时也方便链式调用和对象的赋值操作。通过返回引用,函数可以返回一个指向已存在的对象的引用,而不需要创建新的对象。

        对于n,是局部变量,存储在栈区,出count函数就会被销毁;

        编译器会先将n的值存储在寄存器中,当count函数栈帧销毁后,将寄存器的值赋给ret;

int count()
{int n = 0;n++;return n;
}int main()
{int ret = count();return 0;
}

        对于变量n,是静态变量,存储在静态区,不会随着count函数的销毁而销毁;

        编译器仍然会先将n的值存储在寄存器中,当count函数栈帧销毁后,将寄存器的值赋给ret;

int count()
{static int n = 0;n++;return n;
}int main()
{int ret = count();return 0;
}

        为什么两种都需要寄存器的帮助?

        如果是返回引用,还需要寄存器的帮助吗?

​
int& count1()
{int n = 0;n++;return n;
}int& count2()
{static int n = 0;n++;return n;
}int main()
{int ret1 = count1();int ret2 = count2();return 0;
}​

        显然不需要,这样就减少了拷贝;

        引用作返回值,同时也可以做可修改的左值,因为引用本质上就是变量的别名,变量当然可修改;

#define N 50//静态顺序表
struct AY
{int a[N];int size;    //大小int capacity;//容量
}//检查是否越界
int& posAt(AY& ay,int i)
{assert(i < N)return ay.a[i];
}int main()
{AY ay;for(int i = 0;i < N;i++){posAt(ay,i) = i * 10;//返回引用可作为可被修改的左值}
}


        iv,修改外部变量:

        引用可以作为函数的返回值,在函数内部对外部的变量进行修改。这种方式可以用于实现一些特殊的操作,如对象的赋值操作符重载等。通过引用,可以直接修改外部的变量,而不需要通过指针等方式。

 

        v,避免空指针:

        引用在定义时必须初始化,并且不能被修改指向其他对象,这样可以避免了指针的空引用问题。使用引用可以更加安全地操作对象,避免了空指针异常的发生。

 


 完~

未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/473145.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#安装CommunityToolkit.Mvvm依赖

这里需要有一定C#基础&#xff0c; 首先找到右边的解决方案&#xff0c;右键依赖项 然后选择nuget管理 这里给大家扩展一下nuget的国内源&#xff08;https://nuget.cdn.azure.cn/v3/index.json&#xff09; 然后搜自己想要的依赖性&#xff0c;比如CommunityToolkit.Mvvm 再点…

Kibana:如何嵌入 Kibana 仪表板

作者&#xff1a;Carly Richmond 像我这样的前端工程师经常提出的要求是将 Kibana 等来源的现有仪表板嵌入到 JavaScript Web 应用程序中。 这是我必须多次执行的任务&#xff0c;因为我们希望快速部署用户生成的视图或允许用户控制给定的视图。 从我们从精彩的开发者社区收到的…

Git 初学

目录 一、需求的产生 二、版本控制系统理解 1. 认识版本控制系统 2. 版本控制系统分类 &#xff08;1&#xff09;集中式版本控制系统 缺点&#xff1a; &#xff08;2&#xff09;分布式版本控制系统 三、初识 git 四、git 的使用 例&#xff1a;将 “ OLED文件夹 ”…

每日一题 429.N叉树的层序遍历

429. N 叉树的层序遍历 描述&#xff1a; 给定一个 N 叉树&#xff0c;返回其节点值的层序遍历。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&#xff09;。 示例 1…

对待不合理需求,前端工程师如何优雅的say no!

曾经有位老板&#xff0c; 每次给前端提需求&#xff0c;前端都说实现不了&#xff0c;后来他搜索了一下&#xff0c;发现网上都有答案。他就在招聘要求上加了条&#xff1a;麻烦你在说不行的时候&#xff0c;搜索一下。 上面是一个段子&#xff0c;说的有点极端了&#xff0c;…

萨科微半导体宋仕强介绍说

萨科微半导体宋仕强介绍说&#xff0c;电源管理芯片是指在电子设备系统中&#xff0c;负责对电能的变换、分配、检测等进行管理的芯片&#xff0c;其性能和可靠性直接影响电子设备的工作效率和使用寿命&#xff0c;是电子设备中的关键器件。萨科微slkor&#xff08;www.slkormi…

vmware-17虚拟机安装教程及版本密钥(保姆级,包含图文讲解,不需注册账户)

文章目录 vmware安装教程一、下载vmware二、安装三、破解密匙 vmware安装教程 一、下载vmware 1.进入VMware官网&#xff1a;https://www.vmware.com/sg/products/workstation-pro.html 2.向下翻找到&#xff0c;如下界面并点击“现在安装” 3.稍事等待以下直到出现以下界面…

论文阅读_用模型模拟记忆过程

英文名称: A generative model of memory construction and consolidation 中文名称: 记忆构建和巩固的生成模型 文章: https://www.nature.com/articles/s41562-023-01799-z 代码: https://github.com/ellie-as/generative-memory 作者: Eleanor Spens, Neil Burgess&#xff…

什么软件可以监控电脑屏幕?

随着信息技术的飞速发展&#xff0c;电脑已成为企业日常运营不可或缺的工具。然而&#xff0c;这也带来了一系列的管理挑战&#xff0c;如何确保员工高效工作、避免信息泄露、监控不当行为等成为了企业迫切需要解决的问题。在这种背景下&#xff0c;电脑屏幕监控软件应运而生&a…

ubuntu22.04安装jenkins并配置

准备 更新系统 sudo apt update sudo apt upgrade环境准备 jdk 安装 sudo apt install openjdk-11-jdk验证 java -versiongit ubuntu配置git maven ubuntu配置maven 部署 添加 Jenkins 存储库 导入Jenkins存储库的GPG密钥 wget -q -O - https://pkg.jenkins.io/de…

自动更改由VSCode调试器创建的默认launch.json文件

File -> Preference -> Settings 修改下面的部分

C语言程序设计(第四版)—习题7程序设计题

目录 1.选择法排序。 2.求一批整数中出现最多的数字。 3.判断上三角矩阵。 4.求矩阵各行元素之和。 5.求鞍点。 6.统计大写辅音字母。 7.字符串替换。 8.字符串转换成十进制整数。 1.选择法排序。 输入一个正整数n&#xff08;1&#xff1c;n≤10&#xff09;&#xf…