C++基础篇(2)

目录

前言

1.缺省参数

2.函数重载

 2.1函数重载的基本规则

​编辑2.2注意事项

2.3 重载解析(Overload Resolution)--补充内容

3.引用

3.1引用的概念和定义

3.2引用的特性

3.3引用的使用

3.4const引用

4.指针和引用的关系

结束语

前言

上节小编讲解了命名空间和函数的输入输出,本节将讲解缺省参数,函数重载等知识。

1.缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参,则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左
依次连续缺省,不能间隔跳跃给缺省值。
例如(错误示范)
void func(int a, double b = 3.14, const char* c = "default") { // 正确// 函数体
}void func(int a = 1, double b, const char* c = "default") { // 错误,不能跳过 b// 函数体
}
#include <iostream>
using namespace std;
void func(int x=0) {cout << x << endl;
}
int main() {
// 没有传参时,使⽤参数的默认值
// 传参时,使⽤指定的实参func();func(10);return 0;
}

运行结果:

0

10

带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
int main()
{Func1();Func1(1);Func1(1, 2);Func1(1, 2, 3);Func2(100);Func2(100, 200);Func2(100, 200, 300);Func2(100, ,300);//错误return 0;
}

03e0f99269104ad9857a995b841d7c85.png

函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
值。
// 在头文件中的函数声明
void func(int a = 1, double b = 3.14, const char* c = "default");// 在源文件中的函数定义
void func(int a, double b, const char* c) {// 函数体
}

2.函数重载

在C++中,函数重载(Function Overloading)是指在同一作用域内可以存在多个同名函数,但这些函数的参数列表(参数的个数、类型或者顺序)必须不同。编译器会根据传递给函数的参数来决定调用哪一个重载版本。

 2.1函数重载的基本规则
 

1.参数数量不同:函数可以具有不同数量的参数。

#include <iostream>
using namespace std;
int Add(int a, int b) {return a + b;
}int Add(int a, int b, int c) { return a + b + c;
}int main() {int sum1 = Add(10, 20);   double sum2 = Add(10,20,30); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}

7a6272792b2f45329a1ae531db18f8ee.png
2. 参数类型不同:函数可以具有不同类型的参数。

#include <iostream>
using namespace std;
int add(int a, int b) {cout << "int add(int a, int b)"<<endl;return a + b;}
double add(double a, double b) {cout << "double add(double a, double b)"<<endl;return a + b;}
int main() {int sum1 = add(10, 20);   double sum2 = add(1.5, 2.5); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}

f1f6cddca9174c738581aee06c9f704e.png
3. 参数顺序不同:如果参数类型相同,但顺序不同,也可以构成重载。

#include <iostream>
using namespace std;
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;
}
int main() {f(10, 'c');f('c', 10);return 0;
}

668ff08bb9574e458d0164b9479f4544.png

2.2注意事项

- 返回类型:函数重载与返回类型无关,即不能仅通过改变返回类型来重载函数。
-默认参数:使用默认参数的函数可能会导致重载解析的歧义,应当小心使用。

int Add(int a, int b) {return a + b;
}double Add(int a, int b) { // 错误:不能仅通过返回类型来重载return static_cast<double>(a + b);
}
#include <iostream>
using namespace std;// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f()
{cout << "f()" << endl;
}
void f(int a = 10)
{cout << "f(int a)" << endl;
}
int main() {f();return 0;
}

fd43ff7a5a1a4f20832734c981822d9e.png

2.3 重载解析(Overload Resolution)--补充内容

当调用一个重载函数时,编译器会根据提供的实参和每个重载函数的形参列表进行匹配,以确定调用哪一个函数。这个过程称为重载解析。如果编译器无法明确地确定应该调用哪个函数,或者找到多个合适的匹配,就会产生编译错误。

函数重载是C++多态性的一种形式,它允许程序员使用相同的名字来执行相似的操作,这增强了代码的清晰性和可读性。

3.引用

3.1引用的概念和定义

在 C++ 中,引用是一个变量的别名。一旦一个引用被初始化为指向一个对象,它就不能被重新绑定到另一个对象。这与指针不同,指针可以在任何时候指向不同的对象。

引用的概念

  • 别名:引用为另一个变量提供了一个额外的名字,它和原变量指向相同的内存位置。
  • 不可变性:一旦引用被初始化,它就不能被重新赋值为另一个变量的引用。
  • 无需解引用:使用引用时,不需要像指针一样使用 * 操作符来访问引用的值。
  • 效率:引用在传递参数时可以避免不必要的复制,特别是对于大型对象来说,使用引用可以提高效率。

引用的定义

引用在 C++ 中是这样定义的:

类型 &引用名 = 原变量名;

一些有趣的实例:

比如:水浒传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;

这里,类型 是原变量的类型,& 符号用于声明引用,引用名 是你给引用起的名字,而 原变量名 是已经存在的变量。

1f4ad6d33e3f44d49138ef72580f55b2.png

#include <iostream>
using namespace std;
int main() {int a = 520;int& b = a;int& c = a;int& d = b;++d;
// 引⽤:b和c是a的别名cout << &a << endl;cout << &b << endl;cout << &c << endl;
// 也可以给别名b取别名,d相当于还是a的别名cout << &d << endl;
//地址,值都是一样的cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;return 0;
}

e4fe0f1e22424434810ab50ad72d01dc.png

3.2引用的特性

• 引用在定义时必须初始化
• 一个变量可以有多个引用
• 引用一旦引用一个实体,再不能引用其他实体
#include<iostream>
using namespace std;
int main()
{int a = 10;// 编译报错:“ra”: 必须初始化引⽤//int& ra;int& b = a;int c = 20;// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向,// 这⾥是⼀个赋值b = c;cout << a << endl;cout << b << endl;cout << c << endl;b = 30;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << a << endl;cout << b << endl;cout << c << endl;return 0;
}

c4480a75ea4b458eb7c23cc2e3926981.png

3.3引用的使用

1.引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
2.引用传参跟指针传参功能是类似的,引用传参相对更方便一些。
3.引用返回值的场景相对比较复杂,小编实力有限,以后等知识丰富了再会详细讲解。
4.引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向,java的引用可以改变指向。
5.一些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,用的是简化程序,避开复杂的指针。
代码实例:
#include <iostream>
using namespace std;
void Swap(int& x, int& y) {int temp = x;x = y;y = temp;
}
int main() {int x = 520, y = 1314;cout << x << " " << y << endl;Swap(x, y);cout << x << " " << y << endl;return 0;
}

816ca5a6fbd5403c9824d39573ac5af3.png

#include<iostream>
#include <assert.h>
#include <stdlib.h> using namespace std;
typedef int STDataType;
typedef struct Stack {STDataType* a;int top;int capacity;
} ST;void STInit(ST& rs, int n = 4) {rs.a = (STDataType*)malloc(n * sizeof(STDataType));rs.top = 0; // 栈顶初始化为 0,表示栈为空rs.capacity = n;
}void STPush(ST& rs, STDataType x) {// 满了,扩容if (rs.top == rs.capacity) {printf("扩容\n");int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("realloc fail");return;}rs.a = tmp;rs.capacity = newcapacity;}rs.a[rs.top] = x; rs.top++; // 栈顶指针上移
}int& STTop(ST& rs) {assert(rs.top > 0); // 确保栈不为空return rs.a[rs.top - 1]; // 返回栈顶元素的引用
}int main() {ST st1;STInit(st1);STPush(st1, 1);STPush(st1, 2);cout << STTop(st1) << endl; // 输出栈顶元素 2STTop(st1) += 10; // 通过引用修改栈顶元素cout << STTop(st1) << endl; // 输出修改后的栈顶元素 12return 0;
}

bc232eec8078412581694a024397c8b1.png

3.4const引用

在 C++ 中,const 引用是一种特殊类型的引用,它被用来引用一个对象,同时保证这个引用不会修改所引用的对象。这种引用通常用于函数参数,以允许函数读取传递的对象,但不允许通过引用修改它。

以下是 const 引用的几个关键点:

声明 const 引用

const 类型 &引用名 = 引用的对象;

这里,类型 是被引用对象的类型,引用名 是你给引用起的名字,而 引用的对象 是你想要引用的实际对象。

使用 const 引用的好处

  • 保护数据不被修改:通过 const 引用,你可以确保传递给函数的参数不会被函数修改。
  • 可以引用临时对象和字面量const 引用可以引用右值(如字面量或临时对象),这是非 const 引用无法做到的。
  • 可以与任何类型的对象兼容:只要类型可以转换为 const 引用的类型,就可以创建 const 引用。

示例

不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样一些场景下a*3的和结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对象存储中间值,也就是时,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就触发了权限放大,必须要用常引用才可以。
int main()
{
const int a = 10;
// 编译报错:error C2440: “初始化”: ⽆法从“const int”转换为“int &”
// 这⾥的引⽤是对a访问权限的放⼤
//int& ra = a;
// 这样才可以
const int& ra = a;
// 编译报错:error C3892: “ra”: 不能给常量赋值
//ra++;
// 这⾥的引⽤是对b访问权限的缩⼩
int b = 20;
const int& rb = b;
// 编译报错:error C3892: “rb”: 不能给常量赋值
//rb++;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 10;
const int& ra = 30;
// 编译报错: “初始化”: ⽆法从“int”转换为“int &”
// int& rb = a * 3;
const int& rb = a*3;
double d = 12.34;
// 编译报错:“初始化”: ⽆法从“double”转换为“int &”
// int& rd = d;
const int& rd = d;
return 0;
}

#include <iostream>
using namespace std;void print(const int& x) {cout << x << endl;// x = 5; // 错误:不能通过 const 引用修改对象
}int main() {int a = 10;const int& ref = a; // 创建一个对 a 的 const 引用// ref = 20; // 错误:不能通过 const 引用修改对象print(a); // 正确:传递 intprint(20); // 正确:传递字面量,通过 const 引用允许return 0;
}

注释前的错误:

c0263619b1d34b908ea737dbd566f98b.png

正确运行结果:

dd74ed8c39d14563875c87faf1f56ec2.png

注意事项

  • 一旦 const 引用被初始化,它就不能再引用其他对象。
  • const 引用不能引用非 const 对象的地址,如果需要引用非 const 对象,必须显式地声明非 const 引用。

总之,const 引用在 C++ 中是一种非常有用的特性,它不仅提供了对数据的保护,还增加了代码的灵活性和安全性。

4.指针和引用的关系

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,能有重叠性,但是各有自己的特点,互相不可替代。
• 语法概念上引用是一个变量的取别名不开空间,指针是存储一个变量地址,要开空间。
• 引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引用在初始化时引用一个对象后,就不能再引用其他对象;而指针可以在不断地改变指向对象。
• 引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
• sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些。

结束语

本篇博客也就到此结束啦,C++ 的入门也差不多了,下个阶段我们将步入类和对象的学习!!!
最后支持小编的友友和大佬们点个赞吧,也欢迎大家在评论区多多交流,感谢大家的支持!!!

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

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

相关文章

感应灯光画纯电路开源版本

前言 之前那版灯光画用的从垃圾佬淘的电路板拼出来的&#xff0c;功能不全&#xff0c;显示效果不太好而且无法固定到相框上&#xff0c;这次改版用的嘉立创smt&#xff0c;贴了5片板子&#xff08;19元&#xff09;&#xff0c;功能上的改进是加了无极触摸调光、添加了黄白两…

debian固定ip

debian固定ip 前言 安装好的Debian系统后&#xff0c;为了确保每次登陆的ip不变&#xff0c;需要固定 方法 命令如下 ip addr | grep inet因为有有线网和无线网 2 种连接方式&#xff0c;因此需要区别。 其中 enp 的是有线&#xff0c;wlp 的是无线 查看网关 IP 命令如下 …

互联网末法时代的一些思考

这篇文章也是临时起意&#xff0c;很长一段时间没写个人思考类的文章&#xff0c;主要原因也是时间完全不够用。随着年龄的增长&#xff0c;看待问题的视角也逐渐发生变化&#xff0c;例如从关注现象到关注动机&#xff0c;从关注结果到关注起因&#xff0c;2021年的时代我曾经…

java面向对象进阶篇--static

一、前言 java进阶篇已经开始了&#xff0c;先从面向对象开始&#xff0c;由于时间原因今天就只更新了static部分&#xff0c;内容上特别详细&#xff0c;一些特别的注意事项也在反复的提醒大家。 温馨提示一下&#xff0c;往后的java篇会越来越难&#xff0c;希望大家能够坚…

P2p网络性能测度及监测系统模型

P2p网络性能测度及监测系统模型 网络IP性能参数 IP包传输时延时延变化误差率丢失率虚假率吞吐量可用性连接性测度单向延迟测度单向分组丢失测度往返延迟测度 OSI中的位置-> 网络层 用途 面相业务的网络分布式计算网络游戏IP软件电话流媒体分发多媒体通信 业务质量 通过…

python编程:从入门到实践(第三版) 笔记

文章目录 资源网站:https://www.ituring.com.cn/book/3038配置VSCode推荐资源网站推荐资源网址 资源网站:https://www.ituring.com.cn/book/3038 配置VSCode 推荐资源网站 推荐资源网址 英文版主页&#xff1a; https://ehmatthes.github.io/pcc_3e 中文版主页&#xff1a; h…

上市公司企业共同机构所有权数据、机构交叉持股数据(2005-2023)

数据来源&#xff1a;基础数据来源于上市公司企业年报 时间跨度&#xff1a;2005-2023年 数据范围&#xff1a;企业层面 数据指标&#xff1a; 参考《中国工业经济》杜勇&#xff08;2021&#xff09;老师的做法&#xff0c;从 3 个维度构造指标反映上市公司共同机构所有权&…

Vue和Element UI 路由跳转

在Vue.js中&#xff0c;使用Vue Router可以方便地实现页面之间的路由跳转。Element UI是一个基于Vue 2.0的桌面端组件库&#xff0c;它本身并不直接提供路由跳转的功能&#xff0c;但你可以在使用Element UI的Vue项目中结合Vue Router来实现这一功能。 以下是一个基于Vue和Ele…

Proxyman for Mac v5.6.1 抓包调试工具

Mac分享吧 文章目录 效果一、下载软件二、功能三、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 四、运行测试1、打开软件 安装完成&#xff01;&#xff01;&#xff01; 效果 一…

【华为OD笔试】2024D卷命题规律解读【分析300+场OD笔试考点总结】

可上 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1441了解算法冲刺训练&#xff08;备注【CSDN】否则不通过&#xff09; 文章目录 相关推荐阅读华为OD笔试2024D卷命题规律解读华为OD算法/大厂面试高频题算法练习冲刺训练 相关推荐阅读 【华为OD笔试】2024D卷机考套题…

C# Opencv实现本地以图搜图

地址&#xff1a;冯腾飞/本地以图搜图

Java面试八股之Redis哨兵机制

Redis哨兵机制 Redis Sentinel&#xff08;哨兵&#xff09;模式是一种高可用解决方案&#xff0c;用于监控和自动故障转移Redis主从集群。以下是对哨兵模式详细过程的描述&#xff1a; 1. 初始化与配置 部署哨兵节点&#xff1a;在不同的服务器上部署一个或多个Redis Sentin…

《算法笔记》总结No.7——二分(多例题详解版)

一.二分查找 目前有一个有序数列&#xff0c;举个例子&#xff0c;假设是1~1000&#xff0c;让我们去查找931这个数字&#xff0c;浅显且暴力的做法就是直接从头到尾遍历一遍&#xff0c;直到找到931为止。当n非常大&#xff0c;比如达到100w时&#xff0c;这是一个非常大的量级…

Linux 线程初步解析

1.线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列。在linux中&#xff0c;由于线程和进程都具有id,都需要调度等等相似性&#xff0c;因此都可以用PCB来描述和控制,线程含有PCB&am…

美联储降息应该更早?高盛:有充分理由7月降息,而非9月

KlipC报道&#xff1a;高盛首席经济学家哈祖斯Jan Hatzius表示&#xff0c;美联储“有充分理由”在7月会议上降息&#xff0c;而非等到9月。 在最新发布的报告中&#xff0c;他表明通胀已经取得了足够的进展&#xff0c;回到了美联储2%的长期目标附近&#xff0c;这将使美联储…

实现将Nginx的每个网站配置单独的访问日志

一、问题描述 Nginx默认的访问日志是不会区分哪个网站有哪些日志的,全部糅杂在一起;如果需要哪个网站有哪些访问日志记录,还需要将访问日志下载下来后筛选,比较麻烦;希望将每个网站对应的日志能够单独记录到对应的日志文件里面,方便排查和管理。 # 进入Nginx默认的日志文…

Nest.js 实战 (一):使用过滤器优雅地统一处理响应体

前言 在我们实际的业务开发中&#xff0c;我们可以看到后端接口返回格式都有一定的要求&#xff0c;假如我们统一规定接口的统一返回格式为&#xff1a; {data: any; // 业务数据code: number; // 状态码msg: string; // 响应信息timestamp: number; // 时间戳 }那么在 Nest.…

【智能算法改进】改进的麻雀搜索算法及其求解旅行商问题

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】麻雀搜索算法&#xff08;SSA&#xff09;原理及实现 2.改进点 改进发现者更新位置 为了使 SSA 算法能够避开向原点收敛的弊端, 将算法向最优位置跳跃的操作转换为向最优位置的移动: X i ,…

自己动手写一个滑动验证码组件(后端为Spring Boot项目)

近期参加的项目&#xff0c;主管丢给我一个任务&#xff0c;说要支持滑动验证码。我身为50岁的软件攻城师&#xff0c;当时正背着双手&#xff0c;好像一个受训的保安似的&#xff0c;中规中矩地参加每日站会&#xff0c;心想滑动验证码在今时今日已经是标配了&#xff0c;司空…

一个篇文章告诉你一个APP前端搭建有多简单

用uni-app 1.新建uni-app项目 点击项目 2.创建 最后点击右下方创建 3.添加tarbar 首先你要创建几个页面这里比如说我有两个页面的tarbar首页(home)和我的(userIndex) 在pages目录下右键新建页面即可