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

C++初始02——函数参数缺省、函数重载和引用

一.参数缺省

参数缺省指的是,在函数的参数列表中,针对某些或全部参数,给其定义一个初始值,当调用函数传参时,如果不指定参数数值,则会利用默认值进行函数参数的运算。

函数参数缺省,也可以成为参数默认。

int Add(int x = 1, int y = 2) { return x + y; } int main() { int a = 0; int b = 0; std::cin >> a >> b; std::cout << a<<" " << b << '\n'; std::cout << Add() << std::endl; std::cout << Add(a,b) << std::endl; return 0; }

例如上面这段程序,定义了Add函数,其内部有两个参数x和y,默认值分别指定为1和2。如果调用Add函数,不进行传参,返回值结果就是1+2 =3。如果进行传参,则会返回传参的两个值相加的结果。

需要格外注意的是,在传参过程中,只能从左向右依次传参,不可以跳过某些参数进行传参。

Add(a,b) Add(a) Add(); Add(,b)//错误

例如上面这段代码,前三种都是正确的情况,可以全部传参,可以只传a,也可以都不传,但不可以跳过a直接进行b的传参。

函数参数的缺省分为全缺省和半缺省:

全缺省:所有函数参数均以指定默认值,如上例,Add中参数x默认值为1,y默认值为2,两个参数都指定了默认值。

半缺省:半缺省指的是函数某些参数的参数值缺省,需要格外注意,参数的默认值需要从右向左进行缺省

Add(int x = 1 , int y =2)//全缺省 Add(int x , int y = 2)//半缺省

同时需要注意,如果函数的声明和定义分开写了,那么函数参数的默认值只需要在头文件中给出即可。

二. 函数重载

在C语言中,是不允许出现定义同名函数的情况。例如同时想实现一个交换函数Swap,如果交换不同类型的值,例如double和int,则需要写两个Swap函数,而在C语言中不可以同时命名为Swap,需要对函数名称进行一定程度的区分,例如Swap_int 、Swap_double。

而在C++中,实现了函数的重载(重名),对函数的定义更加灵活。

void Swap(int* x, int* y) { int tmp = *x; *x = *y; *y = tmp; } void Swap(double* x, double* y) { double tmp = *x; *x = *y; *y = tmp; }

如上例所示,利用同一个Swap名称,可以同时定义出int和double两种类型的交换函数,在真正进行函数调用时,只需要传递不同的参数,即可实现自动调用int或double类型的Swap函数。

函数重载需要满足以下几种情况:

1.参数类型不同

void Swap(int* x, int* y) { int tmp = *x; *x = *y; *y = tmp; } void Swap(double* x, double* y) { double tmp = *x; *x = *y; *y = tmp; }

参数类型不同,只需要传参的过程中进行不同类型参数的传递即可,不会引起歧义。

2.参数个数不同

void f() { cout << 1 << endl; } void f(int a = 1) { cout << a << endl; }

第一个函数直接进行调用即可,而第二个参数需要进行传参。

但对于这个示例,需要注意,由于函数缺省值的存在,如果调用第二个函数的过程中,参数缺省,就会和第一个函数发生歧义,程序会编译报错。

3.参数类型顺序不同

void f(int a, char b) { cout << a << b << endl; } void f(char a, int b) { cout << a << b << endl; }

本质就是参数类型不同。

4.返回值的不同,不能作为函数的重载条件。

int f() { return 1; } double f() { return 1.1 }

如该例,进行函数调用的时候,无法判断调用哪个f(),程序会编译报错。

三.引用

引用是为已经存在的变量起了一个别名,编译器并没有为它实际开辟空间,它和它所引用的变量共同指向同一块内存空间。

基本语法如下:

int main() { int a = 0; int& b = a; //在这里,b就是a的引用,b就是a的另一个名字 cout << &a << endl; cout << &b << endl; //从这里可看出,a和b指向同一块空间 int& c = b; //c是b的别名,同样c也是a的别名,最终都是指向a这块空间 cout << &c << endl; //三者地址相同 int x = 1; c = x; cout << a << endl;//对引用赋值,同样也会改变原数值 cout << &c << endl;//指向的空间并没有改变。 return 0; }

如该例所示,首先创建了一个变量a,然后对a创建了一个引用b,引用的操作符和取地址操作符相同。输出a和b的地址,可以发现他们指向了同一块区域。

再对b创建一个引用c,那么a b c同时指向同一块区域,它们三者的数值、地址均相同。

如果此时再定义一个新变量x,然后进行赋值操作c = x,会发现,a b c 的数值均发生改变,而地址不发生改变。

由该例子可以得出一些结论:

1.引用在创建时必须要初始化。

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

3.引用一旦有了一个实体,就不能改变。

3.1引用的实际应用

//引用的使用场景和使用方式 typedef struct Slt { int* arr; int size; int capacity; }Slt; void Swap(int& x, int& y) { int tmp = x; x = y; y = tmp; } void SltInit(Slt& s , int n =4)//缺省参数为4,默认创建4个空间的大小 { int* tmp = (int*)calloc(n, sizeof(int)); if (tmp == NULL) { exit(EXIT_FAILURE); } //传递的是引用,不再是指针,因此对结构体成员的访问用操作符 " . " s.arr = tmp; s.capacity = 4; s.size = 0; } void SltPush(Slt& s , int x) { if (s.size == s.capacity) { s.capacity *= 2; int* tmp = (int*)realloc(s.arr, s.capacity * sizeof(int)); if (tmp == NULL) { perror("Push Realloc error"); exit(EXIT_FAILURE); } s.arr = tmp; tmp = NULL; } s.arr[s.size++] = x; } //返回类型为引用 int SlSearch(Slt& s, int i) { assert(i < s.capacity); return s.arr[i]; } int& SlSearch1(Slt& s, int i) { assert(i < s.capacity); return s.arr[i]; } int main() { int a = 10; int b = 20; Swap(a, b); cout << a << " " << b << endl; //1.进行函数传参,起到类似于指针的作用 //在传参时,传递的参数为引用,甚至没有开辟出空间,相比于指针还要节省空间 //尤其是在结构体传参的过程中。 Slt s1 = { 0 }; SltInit(s1);//传参为s1,在函数中形成一份引用,从而可以实现直接对结构体变量的操控。 SltPush(s1, 1); SltPush(s1, 2); SltPush(s1, 3); SltPush(s1, 4); SltPush(s1, 5); cout << endl; for (int i = 0; i < s1.size; i++) { cout << s1.arr[i] << endl; } cout << endl; //如果直接返回值为int类型,其实际存储到一个新的临时变量中 //该变量属于被const修饰,不能直接修改 //cout << SlSearch(s1, 3)++ << endl; err //如果返回的是引用类型,甚至没有进行空间的开辟 //可以进行修改 cout << ++SlSearch1(s1, 3) << endl; return 0; }

首先简单创建一个顺序表,实现了初始化和基本插入数据的操作。利用在C++中新学到的缺省参数,可以默认给顺序表开辟4个整形空间的大小,如果有额外需要,可以在最开始就指定开辟多大空间的顺序表。

1.函数参数传引用

函数参数传引用,可以起到类似于指针的作用。在 SltInit 和 SltPush函数中,传递的参数均为结构体的引用,所以其并没有在内存中实际开辟出一个结构体大小的空间,而是传递一个已有结构体的别名。在函数内部的操作中,由于不是地址,所以需要利用“ . ”的操作符来实现对结构体对象的访问。

2.返回类型为引用

函数的返回值类型为引用。例如在函数 SlSearch(返回 int 整形) 和 SlSearch1(返回 int& 引用)。在SlSearch函数最后,返回的是一个整形数据,其具体存储在一个临时变量中然后进行返回,该临时变量由系统对其进行常量化处理,不能修改。

而如果利用SlSearch1函数,其返回类型为该值得一个引用,在这个过程中并没有新的临时变量被开辟,而仅仅是原变量得一个别名,所以其可以被修改。

但需要格外注意的是,如果返回类型为引用,处理不好的情况下容易形成空引用

int& f1() { int ret1 = 0; return ret1;//如果在主程序中调用了这个函数,就会形成野引用 } int f2() { return 1; } int main() { int a = f1();//此处就会形成野引用 int& b = f1(); cout << a << endl; cout << b << endl;//虽然这里也可以输出0,但并不稳定 int c = f2(); cout << a << endl; cout << b << endl;//野引用在其他语句或函数调用后,可能就会出问题。 return 0; }

例如该示例,定义函数 f1,返回一个ret1的引用,而 ret1 为 f1 函数中定义出的临时变量,在 f1调用结束之后,f1的函数栈帧销毁,而返回的引用对象仍然为该块空间的值,所以会形成野引用,导致程序运行不稳定。虽然可能对其进行输出仍然能输出原始 ret1 的结果,但是如果运行其它程序,它的结果可能就会发生变化。

所以一个函数可以返回引用类型的前提是,它所返回变量的引用,该变量在函数运行结束后并没有销毁。

http://www.jsqmd.com/news/390036/

相关文章:

  • C++初识—— 命名空间和基本输入输出
  • DBO-RBF多输出【23年新算法】基于蜣螂算法(DBO)优化径向基记忆神经网络(RBF)的多...
  • 地下管廊巡检小车,沿管道行驶,检测异常,输出巡检报告。
  • 深入解析:Vue3 + Element Plus 实现大文件分片上传组件(支持秒传、断点续传)
  • 导师又让重写?用户挚爱的AI论文写作软件 —— 千笔写作工具
  • 【GitHub项目推荐--Auto Company:全自主AI公司运营平台】⭐
  • 缩短键盘触发长按逻辑的停顿时间
  • Mihon/Tachiyomi漫画插件分析(侧重目前插件现状分析和英文插件推荐)
  • LLM | VeRL 相关文档汇总
  • SST专题(2)双有源桥式变换器单移相调制方法特性分析
  • 基于Java的户籍成员综合智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 2026最新!研究生必备的AI论文网站 —— 千笔·专业论文写作工具
  • 小钢炮MiniCPM-SALA 混合注意力架构与低成本训练范式
  • 基于Java的房产中介微信智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 基于Java的户外用品销售智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 效率直接起飞! 降AIGC平台 千笔 VS 灵感ai,专科生专属利器!
  • 基于Java的户籍信息智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 救命神器 10个降AIGC平台深度测评:本科生降AI率必备指南
  • 深度测评AI论文写作软件,千笔·专业论文写作工具 VS 云笔AI,本科生必备神器!
  • 基于Java的户口医保登记智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • AI 问答就是新战场!2026 年特色 GEO 服务商盘点 - 品牌2025
  • [SpringIOC]NoSuchBeanDefinitionException
  • 用实力说话圈粉无数的降AI率网站 —— 千笔·专业降AIGC智能体
  • 赶deadline必备AI论文写作软件 千笔·专业论文写作工具 VS 灵感风暴AI
  • 【GitHub项目推荐--Blind Watermark:基于DWT-DCT-SVD的鲁棒盲水印工具】
  • 从此告别拖延 9个降AI率工具测评:专科生必看的降AI率神器推荐
  • 不踩雷!AI论文写作软件 千笔·专业论文写作工具 VS 文途AI,专科生专属神器
  • MySQL主从库复制中,主库如何查找对应日志文件位置
  • 一篇搞定全流程 10个AI论文写作软件测评:MBA毕业论文+科研写作全场景推荐
  • Web产品后台开发新思路,XinServer 深度解析