C++进阶(一)

个人主页:PingdiGuo_guo

收录专栏:C++干货专栏

前言

本篇博客是讲解函数的重载以及引用的知识点的。

文章目录

前言

1.函数重载

1.1何为函数重载

1.2函数重载的作用

1.3函数重载的实现

2.引用

2.1何为引用

2.2定义引用

2.3引用特性

2.4常引用

2.5使用场景

2.6传值、传引用的效率对比

2.6.1作为参数

2.6.2作为返回值

2.7引用和指针的区别

2.7.1汇编层面

2.7.2语法

总结


1.函数重载

重载是指在同一作用域内,允许定义多个相同名称的函数或方法,但它们的参数列表不同。在调用时,根据参数的数量和类型的不同,编译器会自动选择匹配的函数或方法进行调用。

1.1何为函数重载

函数重载是指在同一个作用域内,允许定义多个函数,它们具有相同的名称但参数列表不同。当调用这个函数时,编译器通过参数的数量、类型或顺序来确定具体调用哪个函数。这样可以根据不同的参数类型或个数来实现同一个功能的不同实现方式。

1.2函数重载的作用

函数重载的主要作用有:

1. 方便使用:通过函数重载,可以使用同一个函数名来表示具有相似功能的函数,提高了函数的可读性和可理解性。

2. 简化编程:函数重载可以简化程序的编写,因为不需要为相似的功能编写不同的函数名,只需要在参数列表中添加不同的参数来区分不同的函数。

3. 提高代码复用性:通过函数重载,可以将相似功能的代码封装在同一个函数中,提高代码的复用性和维护性。

4. 适应不同的数据类型和参数个数:函数重载允许在不同的函数中使用不同的数据类型和参数个数,使函数可以处理不同类型和不同数量的数据。

总之,函数重载提供了一种更灵活和方便的程序设计方式,使函数的使用更加简单和高效。它是一种提高程序可读性、可维护性和可扩展性的重要手段。

1.3函数重载的实现

函数重载分好几种:

1.参数类型不同

#include<bits/stdc++.h>
using namespace std;
//参数类型不同
int da(int s,int a)
{
    cout<<a<<endl;
    return 0;
}
int da(int s,char a)//ok?
{
    cout<<a<<endl;
    return 0;
}
int main()
{
    int s=1,a=2;
    char b='4';
    //组一
    cout<<"1:"<<endl;
    da(s,a);
    da(s,b);
    return 0;
}

运行结果:

2.参数个数不同

#include<bits/stdc++.h>
using namespace std;
//参数个数不同
int ta(int s,int b,int a)
{
    cout<<b<<endl;
    return 0;
}
int ta(int s,int a)//ok?
{
    cout<<a<<endl;
    return 0;
}
int main()
{
    int s=1,a=2;
    int b=4;
    //组二
    cout<<"2:"<<endl;
    ta(s,b,a);
    ta(s,a);
    return 0;
}

运行结果:

3.参数类型顺序不同

#include<bits/stdc++.h>
using namespace std;
//参数类型顺序不同
int ea(int a,char s)
{
	cout<<a<<endl;
	return 0;
}
int ea(char s,int a)
{
	cout<<a<<endl;
	return 0;
}
int main()
{
	int s=1,a=2;
	char b='4';
	//组三
	cout<<"3:"<<endl;
	ea(a,b);
	ea(b,a);
	return 0;
}

运行结果:

2.引用

2.1何为引用

在C++编程语言中,引用概念是一种用于创建别名的机制。通过引用,可以使用一个变量或对象的别名来访问它。

例如,小刘的小名是纯纯,那我们既可以叫他小刘,也可以叫他纯纯。

2.2定义引用

定义引用的语法:

<数据类型> &<引用变量名> = <已存在的变量名>;

以下是一个完整的C++代码示例:

#include <iostream>
using namespace std;
int main() {
    int a = 10;
    int& b = a; // 定义一个整型引用b,它是a的别名
    cout << "a: " << a << endl; // 输出原始的变量a的值
    cout << "b: " << b << endl; // 输出引用b的值
    b = 20; // 修改引用b的值,也会影响到变量a的值
    cout << a << endl; // 输出修改后的变量a的值
    return 0;
}

在上述代码中,变量a是一个整型变量,而引用b是对a的引用。通过输出语句可以看到,变量a和引用b的初始值是相同的,而修改引用b的值后,变量a的值也相应改变。我们定义引用,相当于给变量或对象起了一个别名。

2.3引用特性

 引用在定义时必须初始化
一个变量可以有多个应用
引用一旦引用一个实体,就不能再引用其他实体

#include <iostream>
using namespace std;
int main()
{
    int a = 1;
    //int& b;//引用未初始化
    
    int& c = a;//多个引用
    int& d = a;
    
    cout<<&c<<' '<<&d<<endl;
    
    return 0;
}

运行结果:

2.4常引用

#include <iostream>
using namespace std;
int main()
{
    const int a = 1;
    //int& s=a;//ok?
    //int& b = 10;//ok?
	const int& b = 10;
    float c;
    //int& n=c;//ok?
    return 0;
}

运行结果:

这里都不能运行,a为常量,无法运行,b为常量,无法运行,c和n类型不同,无法运行。

2.5使用场景

C++中引用的使用场景包括以下几个方面:

1. 函数参数传递:通过引用将参数传递给函数,在函数内部修改参数的值,可以直接对原始变量进行操作,避免了拷贝带来的额外开销。

void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 1, y = 2;
    swap(x, y);
    return 0;
}

2. 函数返回值:可以通过引用返回函数内部的局部变量,避免了拷贝带来的开销。

int& max(int& a, int& b) {
    return a > b ? a : b;
}

int main() {
    int x = 1, y = 2;
    int& result = max(x, y);
    return result;
}

 注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回;如果已经返还给系统,则必须使用值传递。即返回的实体必须要比函数的生命周期长,不能返回函数栈上的空间。在使用引用时要确保引用的对象存在,引用不能引用空指针。

2.6传值、传引用的效率对比

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

2.6.1作为参数

代码来啦:

#include <bits/stdc++.h>
struct B{ int a[10000]; };
void TestFunc1(B a){}
void TestFunc2(B& a){}
void TestRefAndValue()
{
    B a;
    // 以值作为函数参数
    size_t begin1 = clock();
    for (size_t i = 0; i < 10000; ++i)
    TestFunc1(a);
    size_t end1 = clock();
    // 以引用作为函数参数
    size_t begin2 = clock();
    for (size_t i = 0; i < 10000; ++i)
    TestFunc2(a);
    size_t end2 = clock();
    // 分别计算两个函数运行结束后的时间
    cout << "TestFunc1(B)-time:" << end1 - begin1 << '\n';
    cout << "TestFunc2(B&)-time:" << end2 - begin2 << '\n';
}

运行结果:

解释:大家可以看到,传引用的效率要“更上一层楼”,但为什么这里的传引用的时间是“0”呢?这是因为它的运行时间太短了,小于1毫秒,所以显示为“0”。

2.6.2作为返回值

代码来啦:

#include <bits/stdc++.h>
struct B{ int a[10000]; };
B a;
// 值返回
B TestFunc1() { return a;}
// 引用返回
B& TestFunc2(){ return a;}
void TestReturnByRefOrValue()
{
    // 以值作为函数的返回值类型
    size_t begin1 = clock();
    for (size_t i = 0; i < 100000; ++i)
    TestFunc1();
    size_t end1 = clock();
    // 以引用作为函数的返回值类型
    size_t begin2 = clock();
    for (size_t i = 0; i < 100000; ++i)
    TestFunc2();
    size_t end2 = clock();
    // 计算两个函数运算完成之后的时间
    cout << "TestFunc1 time:" << end1 - begin1 << '\n';
    cout << "TestFunc2 time:" << end2 - begin2 << '\n';
}

运行结果:

解释:可以看出作为返回值效率更高。

2.7引用和指针的区别

2.7.1汇编层面

在汇编层面上,引用和指针之间的主要区别在于它们在内存中的表示和使用方式。

1. 引用:在汇编层面上,引用通常被实现为指针。当引用被创建时,编译器会将引用作为指针来处理,即将引用的名称作为一个指向所引用对象内存地址的指针。因此,引用在汇编层面上可以通过该指针来访问所引用的对象。与指针不同的是,引用在声明时必须初始化,并且无法更改引用的目标对象。

2. 指针:在汇编层面上,指针直接表示一个内存地址。指针变量存储了所指向对象在内存中的地址。通过加载和存储指令,可以使用指针来访问所指向的对象。与引用不同,指针可以被重新赋值,即指向不同的对象。

在使用引用和指针时,编译器在汇编层面上会生成不同的指令来处理对引用和指针的操作。引用的访问通常会被转换为加载和存储指令,而指针的访问可能会涉及更多的指针运算,如加法和减法操作。

2.7.2语法

1. 声明和初始化:在声明引用时,必须同时进行初始化。例如:int& ref = variable;,其中ref是一个引用,它被初始化为variable。而指针的声明可以先进行,然后再进行初始化,也可以不进行初始化。例如:int* ptr = nullptr;,其中ptr是一个指针,它被初始化为nullptr。

2. 语法符号:引用使用&符号进行声明和引用操作,例如:int& ref = variable;。指针使用*符号进行声明和解引用操作,例如int* ptr = &variable;。

3. 空值和空引用:指针可以被赋予空值(nullptr),表示指针不指向任何有效的内存地址。引用则不允许为空,必须在声明时进行初始化,并且只能引用有效的内存地址。

4. 变量的地址:引用本身没有独立的内存地址,它只是已存在变量的一个别名。而指针是一个变量,它存储了所指向对象在内存中的地址。

5. 内存操作:通过引用操作所引用的变量,可以直接修改引用所指向的内存内容。而通过指针,可以通过解引用操作修改所指向的内存内容。

总的来说,引用必须进行初始化,不能为null,没有独立的内存地址;而指针可以先声明再初始化,可以为null,有自己独立的内存地址。

总结

本篇博客到这里就结束了,制作不易,还是希望大家点赞支持,谢谢大家!

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

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

相关文章

认识一些分布函数-Frechet分布及其应用

1. 何为Frechet分布 Frechet分布也称为极值分布(EVD)类型II,用于对数据集中的最大值进行建模。它是四种常用极值分布之一。另外三种是古贝尔分布、威布尔分布和广义极值分布(Gumbel Distribution, the Weibull Distribution and the Generalized Extreme Value Distributi…

34 Debian如何配置ELK群集

作者:网络傅老师 特别提示:未经作者允许,不得转载任何内容。违者必究! Debian如何配置ELK群集 《傅老师Debian知识库系列之34》——原创 ==前言== 傅老师Debian知识库特点: 1、拆解Debian实用技能; 2、所有操作在VMware虚拟机实测完成; 3、致力于最终形成Debian知识手…

LVS-DR模式详解:提升网站性能的最佳解决方案

LVS-DR模式原理 用户请求到达Director Server&#xff1a; 用户请求到达Director Server&#xff08;负载均衡服务器&#xff09;&#xff0c;数据包首先到达内核空间的PREROUTING链。数据包源IP&#xff1a;CIP&#xff0c;目标IP&#xff1a;VIP&#xff0c;源MAC&#xff1a…

【内存管理之C语言数组】

1.栈空间上的C数组 糟糕的可用性&#xff0c;但是你将在遗留代码中见到它们 相同类型的对象的内存块 大小必须是常量表达式 第一个元素索引为0 2.指针和C数组 更奇怪的是&#xff1a;数组标识符退化为指向第一个元素的指针 3.访问数组 4.堆空间上的C数组 相同类型的对象的内…

数据库开发——并发控制(第十一章)

文章目录 前言并发执行例题一、封锁二、封锁协议三、可串行调度四、总结 学习目标&#xff1a;重点为并发控制的基本概念及几个基本协议 前言 数据库管理系统必须提供并发控制机制&#xff0c;保证事务的隔离性和一致性 并发执行例题 一、封锁 排他锁称为写锁&#xff0c;共…

智能化状态管理:自动状态流转处理模块

目录 基本背景介绍 具体实现 基本数据准备 基本数据表 状态转换常量 状态转换注解 任务处理模版 各任务实现逻辑 开启比对任务进行处理 降噪字段处理任务处理 开启业务数据比对处理 业务数据比对处理 开始核对数据生成最终报告处理 核对数据生成最终报告处理 状…

小红书教程简化版,从0开始走向专业,小红书-主理人培养计划 (13节)

课程目录 1-小红书分析与拆解.mp4 2-小红书电商玩法.mp4 3-小红书基础信息设置10_1.mp4 4-小红书如何开店&#xff1f;.mp4 5-小红书店铺设置&#xff08;1&#xff09;.mp4 5-小红书店铺设置.mp4 6-小红书笔记制作与产品发布.mp4 7-小红书运营的文案与标题.mp4 8-小红…

Spring Boot 自定义Starter

自定义starter 创建pom项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.ap…

MySQL的三种重要的日志

日志 Mysql有三大日志系统 Undo Log&#xff08;回滚日志&#xff09;&#xff1a;记录修改前的数据&#xff0c;用于事务回滚和 MVCC&#xff08;多版本并发控制&#xff09;。 Redo Log&#xff08;重做日志&#xff09;&#xff1a;记录数据变更&#xff0c;用于崩溃恢复&…

XAMPP PHP-CGI 远程代码执行漏洞(CVE-2024-4577)

漏洞概述&#xff1a; PHP 是一种被广泛应用的开放源代码的多用途脚本语言&#xff0c;PHP-CGI 是 PHP 自带的 FastCGI 管理器。是一个实现了 CGI 协议的程序&#xff0c;用来解释 PHP 脚本的程序&#xff0c;2024 年 6 月 7 日&#xff0c;推特安全上 orange 公开了其漏洞细节…

基于Wireshark实现对FTP的抓包分析

基于Wireshark实现对FTP的抓包分析 前言一、虚拟机Win10环境配置二、FileZilla客户端的安装配置下载FileZilla客户端安装FileZilla 三、FileZilla Server安装下载FileZilla Server安装 四、实现对FTP的抓包前置工作实现抓包完成抓包 前言 推荐一个网站给想要了解或者学习人工智…

MySQL学习笔记-进阶篇-SQL优化

SQL优化 插入数据 insert优化 1&#xff09;批量插入 insert into tb_user values(1,Tom),(2,Cat),(3,Jerry); 2&#xff09;手动提交事务 mysql 默认是自动提交事务&#xff0c;这样会导致频繁的开启和提交事务&#xff0c;影响性能 start transaction insert into tb_us…

【面经总结】Java基础 - SPI

SPI 什么是 SPI&#xff1f; 提供给服务提供者去使用的一个接口 SPI 的优点 低耦合配置灵活多态性 SPI 的应用场景 JDBCSLF4J 日志

Pandas AI:最棒的大模型数据分析神器!

暑期实习基本结束了&#xff0c;校招即将开启。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解惑答疑&…

C++ 46 之 关系运算符的重载

#include <iostream> #include <string> using namespace std;class Students06{ public:string m_name;int m_age;Students06(string name, int age){this->m_name name;this->m_age age;}// 重载了 bool operator(Students06 &stu){if(this->m_na…

java:spring actuator添加自定义endpoint

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89437274 # 项目代码 【pom.xml】 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId&…

Cocos2d-x 4.0 工程首次建立与编译(Mac m1)

Mac m1芯片下将cocos2d-x升级至4.0版本后&#xff0c;官方剔除了不同平台的工程以及变更了编译方式&#xff0c;直接使用cmake构建&#xff0c;需要做一些前置的准备工作。 环境准备&#xff1a; 项 版本 备注 MacOS10.3 or laterpython2.7.16(建议>2.7.10)cmake3.29.3Do…

Android 工程副总裁卸任

Android 工程副总裁卸任 Android工程副总裁Dave Burke宣布&#xff0c;他将辞去领导Android工程的职位&#xff0c;将重心转向“AI/生物”项目。不过&#xff0c;他并没有离开Alphabet&#xff0c;目前仍将担任Android系统开发顾问的角色。 Burke参与了Android系统的多个关键…

TCP三次握手的过程

一、什么是TCP TCP是面向连接的、可靠的、基于字节流的传输层通信协议。 二、TCP的头部格式 序列号:在建立连接时由计算机生成的随机数作为其初始值&#xff0c;通过SYN包传给接收端主机&#xff0c;每发送一次数据&#xff0c;就「累加」一次该「数据字节数」的大小。用来解…

155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题

设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…