C++:函数重载和引用

hello,各位小伙伴,本篇文章跟大家一起学习C++:函数重载和引用,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 !

文章目录

  • 函数重载
    • 1.函数重载的概念
    • 为什么C++支持函数重载
  • 引用
    • 引用的概念
    • 引用特性
    • 引用的使用场景
      • 1.做参数
      • 2.做返回值
    • 传值、传引用效率比较
    • 引用和指针的区别

函数重载

1.函数重载的概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

要注意是同一作用域,不同作用域可以同名,但是不属于函数重载

1.参数个数不同:

void f(int a)
{
	printf("%d\n",a);
}
void f(int a,int b)
{
	printf("%d %d\n",a,b);
}

2.参数类型不同:

void f(int a,int b)
{
	printf("%d %d\n",a,b);
}
void f(double a,double b)
{
	printf("%lf %lf\n",a,b);
}

3.参数类型顺序不同:

void f(int a,char b)
{
	printf("%d %c\n",a,b);
}
void f(char b,int a)
{
	printf("%d %c\n",a,b);
}

在函数重载时要注意可能会发生分歧,例如:

#include<iostream>
using namespace std;

void f(int a)
{
	cout<<a<<endl;
}
void f(char a)
{
	cout<<a<<endl;
}
int main()
{
	int a = 1;
	f(a);
	return 0;
}

上述代码会报错,因为编译器不知道要调用哪一个f()函数,在传参时a可以隐式转换为char类型,这样就发生了分歧。

为什么C++支持函数重载

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
举个例子,a.cpp调用b.cpp中的Add()函数,那么链接器看到a.o调用Add()函数,但没有地址时,就会在去b.o寻找Add()的地址,然后链接在一起。
a.o、b.o分别为a.cpp、b.cpp预处理、编译、汇编后得到的文件

那么链接器怎么去找呢?
C++会使用已经修饰过的了Add()函数去寻找,怎么修饰与编译器有关,而C语言会直接使用Add这个函数名去寻找,那么两个一模一样的函数名,自然会发生分歧,使得编译器不知道走哪一个。

总的来说C++在链接时,会使用已经修饰过的函数名去寻找地址,函数参数个数不同、参数类型不同、参数类型顺序不同,修饰后的函数名自然不同,从而不会发生分歧。

!!!知道了为什么支持函数重载后,还有一点细节:返回值不同,构成函数重载吗?
答案是:不支持

如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办
法区分。

引用

引用的概念

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

举个例子:陈明的别名是小明,但是小明就是陈明,指的是同一个人。
使用:类型& 引用变量名(对象名) = 引用实体;
例子:

int main()
{
	int a = 1;
	int& b = a;
  //   int       &   	b 	    =      a;
  //(引用类型)  &  (引用变量)	=  (引用实体)
	b = 3;
	cout<<a<<endl;
	printf("%p\n",&a);//表达式1
	printf("%p\n",&b);//表达式2
	return 0;
}

猜猜a的值为多少?没错,答案是3。
前面讲到,它和它引用的变量共用同一块内存空间,所以b指的就是ab的值改变,那么a当然会变,所以表达式1表达式2打印的结果一样,都是同一个地址。
在这里插入图片描述
注意:引用类型必须和引用实体是同种类型的
相信小伙伴们就能很容易理解,那么细节来了:

int main()
{
	const int a = 1;
	int& b = a;

	return 0;
}

这么些是否正确呢?相信聪明的小伙伴们一眼就看出答案:这么些是错误的。
const修饰a,那么a是不能改变的,而b并没有const修饰,所以b可以改变,也就是权限被放大了,本来a自身都不能改变,凭什么b可以。
再来:

int main()
{
	int a = 1;
	const int& b = a;

	return 0;
}

这么写b不能改变,a可以,权限被缩小,是可以的。
继续:

int main()
{
	int a = 1;
	const int* pa = &a;
	int*& b = pa;

	return 0;
}

很明显,这么写是错的,权限被放大了。
那么这个:

int main()
{
	int a = 1;
	int* const pa = &a;
	int*& b = pa;

	return 0;
}

这么写是正确的。

这两个声明之间存在重要的区别,这涉及到C++中指针和const关键字的使用。

  1. int* const pa = &a;

    • 这里 pa 是一个指针,它指向一个整数(int*)。
    • 关键字 const 出现在 * 前面,表示指针本身是常量,即指针一旦指向了某个地址之后,就不能再指向其他地址。
    • 也就是说,pa 是一个常量指针,它的值(即指向的地址)不可以被改变,但是它所指向的值可以被修改。
  2. const int* pa = &a;

    • 这里 pa 是一个指向常量整数的指针。
    • 关键字 const 出现在 int 前面,表示指针所指向的值是常量,即不能通过 pa 修改所指向的值。
    • 也就是说,pa 是一个指针,它可以指向任意整数,但通过 pa 只能读取所指向的值,而不能修改。

总结来说,int* const pa = &a; 表示 pa 是一个指针常量,而 const int* pa = &a; 表示 pa 是一个指向常量整数的指针。

引用特性

  1. 引用在定义时必须初始化(你总不能想到一个别名先放着,看到谁就给谁用吧)
int& a;//这么些是错的
  1. 一个变量可以有多个引用
int a = 1;
int& b = a;
int& c = a;
int& d = a;
  1. 引用一旦引用一个实体,再不能引用其他实体
int a = 1;
int& b = a;
int c = 1;
b = c;//这么些是错的

引用的使用场景

1.做参数

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 1;
	int b = 2;
	int& c = a;
	int& d = b;
	Swap(c,d);
	return 0;
}

2.做返回值

int& Test1()
{
	int n = 0;
	n++;
	return n;
}

int main()
{
	int a = 0;
	int& b = a;
	b = Test1();
	cout << a;
	return 0;
}

传值、传引用效率比较

我们知道:

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

所以,传引用的效率比传值的效率更高,引用作为返回值比值作为返回值效率更高。

引用和指针的区别

语法概念上,引用是没有独立空间的,他就是引用实体的另一个名字,和其引用实体共用同一块空间。

int main()
{
 int a = 10;
 int& ra = a;
 
 cout<<"&a = "<<&a<<endl;
 cout<<"&ra = "<<&ra<<endl;
 return 0;
}

底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

int main()
{
 int a = 10;
 
 int& ra = a;
 ra = 20;
 
 int* pa = &a;
 *pa = 20;
 
 return 0;
}

我们来看其汇编代码对比指针和引用
在这里插入图片描述
可以看出操作上是一样的。

引用和指针的不同点:

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

好啦,这篇文章就到此结束了
所以你学会了吗?

好啦,本章对于C++:函数重载和引用的学习就先到这里,如果有什么问题,还请指教指教,希望本篇文章能够对你有所帮助,我们下一篇见!!!

如你喜欢,点点赞就是对我的支持,感谢感谢!!!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot+Vue的儿童书法机构管理系统

一、项目背景介绍&#xff1a; 儿童书法机构的管理是一个具有挑战性的任务&#xff0c;需要有效的信息管理和资源分配。传统的手动管理方式存在着效率低下、易出错等问题。为了解决这些问题&#xff0c;基于SpringBootVue的儿童书法机构管理系统应运而生。该系统利用现代化的技…

代码随想录第三十一天 | 贪心算法P1 | ● 理论基础 ● 455. ● 376. ● 53.

理论基础 题目分类 一般解题步骤 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 这个四步其实过于理论化了&#xff0c;我们平时在做贪心类的题目 很难去按照这四步去思考&…

数据结构:顺序表的基本操作!(C语言)

一、静态存储 #include <stdio.h> #include <stdlib.h>/*[1].定义静态顺序表的最大容量*/ #define MaxSize 10/*[2].自定义数据元素的数据类型*/ typedef int ElemType; 1. 静态分配的定义结构体 /*[3].静态分配的结构体定义*/ typedef struct {ElemType data[M…

最新AI创作系统ChatGPT网站系统源码+Ai绘画网站源码+Suno-v3-AI音乐生成大模型(sparkAi系统V6版本)

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

rt-thread的nfs如何实现软硬件对接

rt-thread&#xff08;下面简称rtt&#xff09;有一个封装好的的虚拟文件系统&#xff0c;提供了一套通用的io文件接口例如 open,write,read这些&#xff0c;从没看过rtt的代码也没用过&#xff0c;文件系统在刚毕业的时候只是用过fatfs但没去纠结过。今年1月份听同事说只需要打…

C++(语法以及易错点2)

1.内联函数 1.1 概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 ​int ADD(int a,int b) {return ab; }​ 1.2 特性 1. inline是一种以空间换时间…

Java数据结构栈

栈&#xff08;Stack&#xff09; 概念 栈是一种先进后出的数据结构。 栈的使用 import java.util.Stack; public class Test {public static void main(String[] args) {Stack<Integer> s new Stack();s.push(1);s.push(2);s.push(3);s.push(4);System.out.println(s…

精密电阻阻值表和电容容值表

前面2张是电阻阻值表&#xff08;E-96/0603/1%&#xff09; 常见贴片电容的容值表

【智能优化算法】非洲秃鹫优化算法:一种新的全局优化问题的自然启发的元启发式算法

非洲秃鹫优化算法&#xff08;AVOA&#xff09;发表在中科院一区Computers & Industrial Engineering期刊上的论文“African vultures optimization algorithm: A new nature-inspired metaheuristic algorithm for global optimization problems" 01.引言 元启发式算…

DAY16|104.二叉树的最大深度,111.二叉树的最小深度,222完全二叉树的个数

文章目录 104.二叉树的最大深度111.二叉树的最小深度222.完全二叉树的个数 104.二叉树的最大深度 文字讲解&#xff1a;二叉树的层序遍历 视频讲解&#xff1a;二叉树的层序遍历 状态&#xff1a;求深度用前序遍历&#xff0c;求高度用后序遍历&#xff1b; 思路&#xff1a; …

【PSINS工具箱】EKF与UKF滤波

描述 对工具箱SINS/GPS,153例程的修改,将EKF和UKF放在一个文件里面,一次运行可以得到两个滤波的结果(带绘图与误差量化输出)。 片段 运行截图 程序完整源代码 在有工具箱的情况下,直接运行此代码,即可得到结果 % 基于PSINS工具箱的IMU数据生成与滤波 % date:2024-2-…

【系统架构师】-系统可靠性分析与设计

1、可靠性与可用性区别 1、系统可靠性&#xff1a;系统在规定时间内及规定的环境下&#xff0c;完成规定功能的能力&#xff0c;即系统无故障运行的概率 2、系统可用性&#xff1a;在某个给定时间点上系统能够按照需求执行的概率。 可靠性分为软件、硬件可靠性 2、可靠性指标…

LeetCode 第二题:冒泡排序详解 【2/1000】含imagemagick动态效果图

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

使用微带线快速进行电感、电容的等效(Matlab代码实现)

使用微带线快速进行电感、电容的等效&#xff08;Matlab代码实现&#xff09; 目录 使用微带线快速进行电感、电容的等效&#xff08;Matlab代码实现&#xff09;1、高低阻抗微带线的近似等效2、等效电容的ADS测试3、等效电感的ADS测试 1、高低阻抗微带线的近似等效 更加精确的…

利用JS、CSS实现列表自动滑动滚动

零.业务需求 这几天在做大屏项目&#xff0c;对于大屏有很多信息需要实时滚动&#xff0c;废了点力气学的明明白白的&#xff0c;特来记录供大家学习。 0.1实现效果 一.逻辑分析 1.1滑动窗口和滚动条 当我们使用<table>或者<ul>标签时&#xff0c;我们可以制作…

蓝桥杯第十四届C++A组(未完)

【规律题】平方差 题目描述 给定 L, R&#xff0c;问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y,z 使得 。 输入格式 输入一行包含两个整数 L, R&#xff0c;用一个空格分隔。 输出格式 输出一行包含一个整数满足题目给定条件的 x 的数量。 样例输入 1 5 样例输出 …

Redis中的Sentinel(二)

Sentinel 初始化Sentinel状态。 在应用了Sentinel的专用代码之后&#xff0c;接下来&#xff0c;服务器会初始化一个sentinel.c/sentinelState结构(简称Sentinel状态),这个结构 保存了服务器中所有和Sentinel功能有关的状态(服务器的一般状态仍然由redis.h/redisServer保存);…

【java数据结构-二叉树(上)】

java数据结构-二叉树&#xff08;上&#xff09; 二叉树的概念二叉树的节点介绍 二叉树构造如何使用兄弟表示法构造二叉树两种特别的二叉树二叉树的基本性质&#xff1a; 二叉树的存储二叉树的遍历&#xff1a;前序遍历&#xff1a;中序遍历&#xff1a;后序遍历&#xff1a;层…

最新ChatGPT4.0工具使用教程:GPTs,Midjourney绘画,AI换脸,GPT语音对话,文档分析一站式系统

一、前言 ChatGPT3.5、GPT4.0、相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和用户进行创作交流。 然而&#xff0c;GPT-4对普通用户来说都是需要额外付费才可以…

基于RDMA的云服务能力实践与探索

01 背景 随着基于大数据大模型构建的数据系统越来越有商业价值&#xff0c;机器学习的玩家也越来越多&#xff0c;数据量越来越大。为解决海量数据在服务器之间的同步效率问题&#xff0c;RDMA(Remote Direct Memory Access) 技术逐渐走进了网络技术人员的视野。RDMA为什么…