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; // 输出栈顶元素 2
    STTop(st1) += 10; // 通过引用修改栈顶元素
    cout << STTop(st1) << endl; // 输出修改后的栈顶元素 12
    return 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); // 正确:传递 int
    print(20); // 正确:传递字面量,通过 const 引用允许

    return 0;
}

注释前的错误:

c0263619b1d34b908ea737dbd566f98b.png

正确运行结果:

dd74ed8c39d14563875c87faf1f56ec2.png

注意事项

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

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

4.指针和引用的关系

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

结束语

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

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

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

相关文章

16_Shell好用工具:sed

16_Shell好用工具&#xff1a;sed 零、语法解析 sed [选项参数] [模式匹配/sed命令] 文件 命令说明aadd&#xff0c;新增iinsert&#xff0c;新增cchange&#xff0c;修改ssubstitute&#xff0c;替换ddelete&#xff0c;删除pprint, 打印 通常与 -n 连用 一、增&#xff08;…

【JavaScript】聊一聊js中的浅拷贝与深拷贝与手写实现

前言 什么是深拷贝与浅拷贝&#xff1f;深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式。‌在聊深浅拷贝之前咱得了解一下js中的两种数据类型&#xff1a; 基本数据类型&#xff08;6种&#xff09;String、Number、Object、Boolean、null、undefined、symbol&#xff…

数据结构——线性表(C语言实现)

写在前面&#xff1a; 在前面C语言的结构体学习中&#xff0c;我提及了链表的操作&#xff0c; 学习数据结构我认为还是需要对C语言的数组、函数、指针、结构体有一定的了解&#xff0c;不然对于结构体的代码可能很难理解&#xff0c;特别是一些书籍上面用的还是伪代码&#xf…

Day07-员工管理-上传下载

1.员工管理-导出excel 导出员工接口返回的是二进制axios配置responseType为blob接收二进制流文件为Blob格式按装file-saver包&#xff0c;实现下载Blob文件npm install add file-saver导出员工excel的接口 (src/api/employee.js) export function exportEmployee(){return req…

普通人还有必要学习 Python 之类的编程语言吗?

在开始前分享一些编程的资料需要的同学评论888即可拿走 是我根据网友给的问题精心整理的对于编程的重要性&#xff0c;这里就不详谈了。 未来&#xff0c;我们和机器的交流会越来越多&#xff0c;编程可以简单看作是和机器对话并分发给机器任务。机器不仅越来越强大&#xff0…

芯课堂 | Synwit_UI_Creator(ugui)平台之PC端界面设计篇

​今天小编给大家介绍的是华芯微特面向小尺寸TFT-LCD屏驱市场量身打造的Synwit_UI_Creator&#xff08;ugui&#xff09;自研开发套件。 UI_Creator&#xff08;ugui&#xff09;开发套件分为上位机和下位机&#xff0c;以下如无特指&#xff0c;上位机即为PC端设计器/仿真器&…

【香橙派AiPro】基于VGG16的火灾检测模型预测

目录 引言开发板介绍开发板使用准备工作工具文档 拨码开关镜像烧录连接开发板下载MobaXterm网线-SSH连接开发板设置WIFI连接WIFI-SSH连接开发板确定开发板IP方法 Vnc可视化WindowsiPad 开发工具安装 散热风扇基于VGG16的火灾检测模型预测数据集准备目录结构代码操作 安装宝塔最…

RISC-V在线反汇编工具

RISC-V在线反汇编工具&#xff1a; https://luplab.gitlab.io/rvcodecjs/#q34179073&abifalse&isaAUTO 不过&#xff0c;似乎&#xff0c;只支持RV32I、RV64I、RV128I指令集&#xff1a;

2024大模型十大趋势

2024大模型十大趋势 关键要点一、机器外脑时代的智慧探索二、机器外脑、创意生成和情感陪伴三、大模型驱动的新未来&#xff1a;AI带来创意转化与机遇四、人物-行为-场景一体化&#xff1a;未来人工智能的新范式五、未来数字内容生产的基础设施六、共创、共建、共享智能美好未来…

【入门篇】2.3 STM32启动模式(一)

一,Boot引脚分步 二,启动电路 三,启动模式 STM32F4 根据 BOOT 引脚的电平选择启动模式,这两个 BOOT 引脚根据外部施加的电平来决定芯片的启动地址。 下表中 BOOT0 和 BOOT1 是 STM32 芯片上面的两个引脚,用于控制 STM32

哪个牌子充电宝好用?实测倍思、西圣、安克充电宝,哪个值得入手

目前充电宝已经成为我们日常出行的重要依靠。然而&#xff0c;共享充电宝不仅价格昂贵&#xff0c;而且还存在诸多安全隐患&#xff0c;让我们用起来总是不太放心。为了帮大家找到既好用又实惠且安全的充电宝&#xff0c;我们对倍思、西圣、安克这三个热门品牌的充电宝进行了深…

Ubuntu/Linux 安装ITKSnap

文章目录 1. 安装ITKSnap1.1 下载后安装 2.进入opt文件夹改名3. 更改启动项4. 创建硬链接5. 添加桌面启动方式6. 即可使用 1. 安装ITKSnap http://www.itksnap.org/pmwiki/pmwiki.php?nMain.HomePage 1.1 下载后安装 找到下载的文件夹&#xff0c;文件夹内打开terminal。复…

提升代码质量:利用策略模式优化Spring Boot应用的设计

&#x1f4e3;前言 在Spring Boot中使用策略模式&#xff08;Strategy Pattern&#xff09;是一种常见的设计模式实践&#xff0c;它允许在运行时选择算法的行为。策略模式定义了一系列的算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以互换。这样做的好处是使算法…

MyBatis源码中的设计模式1

1. 建造者模式的应用 建造者模式属于创建类模式&#xff0c;通过一步一步地创建一个复杂的对象&#xff0c;能够将部件与其组装过程分开。用户只需指定复杂对象的类型&#xff0c;就可以得到该对象&#xff0c;而不需要了解其内部的具体构造细节。《Effective Java》中也提到&…

CH552G使用IAP下载

常见下载中的方式ISP&#xff0c;IAP&#xff0c;ICP 参考&#xff0c;CH552G中文手册&#xff0c;参考1 ISP&#xff1a;In System Programing&#xff0c;在系统编程。是常见的&#xff0c;使用软件&#xff0c;先将某个引脚&#xff08;例如boot&#xff09;连接到合适的电…

领航Linux UDP:构建高效网络新纪元

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言Udp和Tcp的异同相同点不同点总结 1.1、socket1.2、bind1.3、recvfrom1.4、sendto2.1、代码2.1、说明3.1、代码3.2、说明 引言 在前几篇博客中&#xff0c;我们学习了Linux网络编程中的一些概念。…

【Django】网上蛋糕项目商城-购物车和我的订单功能

1.购物车功能 在首页中的滚动栏的商品&#xff0c;热门商品&#xff0c;新品&#xff0c;以及商品详情中都有加入购物车按钮 在models文件中创建购物车表&#xff0c;用于保存当前用户添加的商品信息 # 购物车表 class ShoppingCar(models.Model):# 用户iduserIdmodels.Integ…

JRT打印设计器解耦

为了让打印设计器可以给多个产品打印通用&#xff0c;那么设计器就不能嵌入太多具体产品的业务信息。比如医院主键、工作组、医嘱关联登。 设计器在设计表的时候就没引入检验部分的依赖&#xff0c;采用产品组唯一标识和产品组业务ID来隔离不同组的模板设计。 维护菜单时候就…

CTFshow--web--xss

目录 web316 web317~319 web320~326 web327 web328 web329 web330 web331 web332 web333 先在自己的服务器写上代码 <?php$content $_GET[1]; if(isset($content)){file_put_contents(flag.txt,$content); }else{echo no data input; }要拿到管理员的cookie , 而…

Java - 程序员面试笔记记录 实现 - Part5

7.1 Struts 优点&#xff1a; 1. MVC模式实现了表现与逻辑的分离&#xff0c;扩展性高。 2. 提供页面导航功能&#xff0c;通过配置文件建立整个系统各部分之间的联系。 3. 集成了一些常用处理功能。 缺点&#xff1a; 1. 仅面向 Web 应用程序开发 2. Action 非线程安全…