初识C++(二)

一、函数重载

C++⽀持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调⽤就表现出了多态行为为,使用更灵活。C语言是不支持同⼀作用域中出现同 名函数的。 

函数重载的基本规则

1.函数名相同:所有重载的函数必须具有相同的函数名。
2.参数列表不同:参数列表必须不同,这可以通过改变参数的数目、类型或顺序来实现。仅通过改变函数返回类型来区分函数重载是不允许的。
3.可以改变返回类型:虽然返回类型不是区分重载函数的依据,但不同的重载函数可以有不同的返回类型。
4.可以抛出不同的异常:不同的重载函数可以声明抛出不同的异常,但这同样不是重载的决定性因素。
5.可以有不同的访问修饰符:比如,一个可以是public,另一个可以是private,但这与重载函数的解析无关。

函数重载示例如下:

#include<iostream>  
using namespace std;// 1、参数类型不同   
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
}
// 2、参数个数不同   
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同   
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;
}void f1(int a = 0) 
{cout << "f1(int a = 0)" << endl; 
}
int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);f1(); f1(5); return 0;
}


二、引用

 在C++中,它是对C语言的重要扩充。引用可以被视为某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。这意味着,当你通过引用访问或修改数据时,实际上是在访问或修改它所引用的那个变量。

定义:

引用的定义方式与指针类似,但使用&符号来标识,而不是指针的*符号。引用的基本语法如下:
其中,&在此处不是求地址运算,而是起标识作用,表示这是一个引用声明。类型指的是目标变量的类型,引用名是你为这个变量定义的别名,而目标变量名则是被引用的原始变量名。

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


特性:

必须初始化:

引用在声明时必须被初始化,因为它必须是某个已存在变量的别名。你不能先声明一个引用,然后再去初始化它。
唯一性:一旦一个引用被初始化为某个变量的别名,它就不能再被改变为另一个变量的别名。
内存共享:

引用和它引用的变量共享同一块内存空间。这意味着,对引用的操作实际上就是对它所引用的变量的操作。
别名:

虽然从概念上讲,引用像是变量的一个别名,不占据额外的内存空间,但在底层实现上,编译器通常会将引用实现为指向位置不可变的指针(即const指针)。因此,引用在实际上也会占用一定的内存空间。
不支持数组:

不能直接定义引用的数组,因为数组是由多个元素组成的集合,而引用需要指向一个具体的变量。但是,可以定义数组的引用,即引用整个数组。
安全性:通过常引用(const引用),可以确保引用的变量不会被修改,从而增加代码的安全性。
多态:

引用是除指针外另一个可以产生多态效果的手段。一个基类的引用可以指向它的派生类实例,从而实现多态。

使用场景:
引用在C++中有广泛的应用场景,包括但不限于:

作为函数的参数,可以避免传递大型对象时的拷贝开销。
作为函数的返回值,可以返回函数内部变量的别名,但需要注意生命周期问题。
在需要别名的地方,如链表节点的指针可以使用引用来简化代码。

#include <iostream>  
using namespace std;
void swap(int& x, int& y) {int temp = x;x = y;y = temp;
}int main() {int a = 1, b = 2;cout << " swap: a = " << a << ", b = " << b << endl;swap(a, b);cout << " swap: a = " << a << ", b = " << b << endl;return 0;
}

三、const引用

const 引用是 C++ 中一种特殊的引用类型,它允许你创建一个对某个对象的引用,但通过这个引用你不能修改被引用的对象。这种机制主要用于保护数据不被意外修改,同时提供对数据的高效访问。

const Type& name = originalObject;

四、指针和引用的关系

1. 语法概念和内存占用

指针:指针可以在声明时不初始化(但这是一个危险的做法,因为未初始化的指针可能指向任意内存位置),也可以在之后的任何时候修改其指向。
引用:引用必须在声明时被初始化,且一旦初始化,就不能再改变其指向(即不能再让引用指向另一个变量)。

2.初始化和修改

指针:指针可以在声明时不初始化(但这是一个危险的做法,因为未初始化的指针可能指向任意内存位置),也可以在之后的任何时候修改其指向。
引用:引用必须在声明时被初始化,且一旦初始化,就不能再改变其指向(即不能再让引用指向另一个变量)。

3. 访问方式

指针:访问指针指向的值时,需要使用解引用操作符*。
引用:引用就像直接使用该变量一样,不需要任何特殊的操作符。

4. sizeof 操作符

指针:无论指向何种类型的变量,指针本身的大小都是固定的(通常是4字节或8字节,取决于平台的地址空间大小)。
引用:在C++中,sizeof对引用的操作实际上返回的是被引用类型的大小,但这并不意味着引用占用了额外的空间,而是标准规定的一种处理方式。

5. 安全性和使用场景

指针:由于指针的灵活性,它们可以被用来实现各种复杂的数据结构和算法,但这也带来了更高的出错风险,如空指针解引用、野指针等问题。
引用:引用提供了一种更安全、更简洁的方式来访问和修改数据,特别是在函数参数传递和返回值时。使用引用可以避免不必要的拷贝,提高效率,同时减少出错的机会。

五、inline函数

定义:

使用inline关键字声明的函数称为内联函数。编译器在编译时尝试将内联函数的调用替换为函数体本身,以减少函数调用的开销。
优点:可以减少函数调用的开销,提高程序运行效率。
缺点:如果过度使用或在不适当的情况下使用(如大型函数),可能会导致编译后的代码体积增大,反而降低性能。
与宏的比较
宏:在C语言中,宏通过预处理器在编译前进行文本替换。这种方法虽然灵活,但容易出错,且不易调试。
inline函数:C++引入inline作为宏的一种更安全、更易于维护的替代方案。与宏相比,inline函数具有类型检查、作用域限制等编译时检查,使得代码更加健壮和易于理解。
编译器行为
不同编译器的差异:不同的编译器对inline的实现和支持程度可能有所不同。有些编译器可能更积极地内联函数,而有些则可能更加保守。
调试版本:在调试(Debug)模式下,许多编译器默认不内联函数,以便更好地进行调试。如果需要在调试模式下内联函数,可能需要通过编译器的特定选项来启用。

vs编译器debug版本下⾯默认是不展开inline的,这样方便调试,debug版本想展开需要设置⼀下 以下两个地方。

#include<iostream>
using namespace std;
inline int Add(int x, int y)
{int ret = x + y;ret += 1;ret += 1;ret += 1;return ret;
}
int main()
{// 可以通过汇编观察程序是否展开 // 有call Add语句就是没有展开,没有就是展开了 int ret = Add(1, 2);cout << Add(1, 2) * 5 << endl;return 0;
}
#include<iostream>
using namespace std;
// 实现⼀个ADD宏函数的常⻅问题 
//#define ADD(int a, int b) return a + b;
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)
// 正确的宏实现 
#define ADD(a, b) ((a) + (b))
// 为什么不能加分号? 
// 为什么要加外⾯的括号? 
// 为什么要加⾥⾯的括号? 
int main()
{int ret = ADD(1, 2);cout << ADD(1, 2) << endl;cout << ADD(1, 2)*5 << endl;int x = 1, y = 2;ADD(x & y, x | y); // -> (x&y+x|y)return 0;
}
// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
// 链接错误:⽆法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z) f(10);return 0;
}

   六、 nullptr

 NULL实际是⼀个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif

nullptr 是 C++11 引入的一个关键字,用于表示空指针常量。在 C++11 之前,空指针通常使用字面量 0 或宏 NULL(定义为 (void*)0 或简单的 0,具体取决于编译器和标准库的实现)来表示。然而,0 和 NULL 都存在类型不明确的问题,因为它们可以被隐式转换为整数或其他指针类型,这可能导致类型安全上的隐患。

nullptr 解决了这个问题,它是一个指针字面量,其类型为 std::nullptr_t,但可以被隐式转换为任何原始指针类型。使用 nullptr 可以使代码更加清晰和类型安全,因为它明确表示了一个空指针,而不是整数或其他类型的值。

int* ptr = nullptr; // ptr 是一个指向 int 的空指针  
if (ptr == nullptr) {  // ptr 是空指针,执行相应逻辑  
}  // 假设有一个函数,其参数是指向 int 的指针  
void func(int* p) {  if (p == nullptr) {  // 处理空指针的情况  }  // ...  
}  // 调用 func,传入 nullptr  
func(nullptr);

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

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

相关文章

Docker基本使用(持续更新中)

1 常用命令 1.1保存镜像到本地 命令如下: docker save -o nginx.tar nginx:latest 举例 结果&#xff1a;在当前目录下多了一个nginx.tar的包 1.2加载本地镜像 命令如下&#xff1a; docker load -i nginx.tar 举例&#xff1a; 查看当前镜像是没有nginx的 加载本地镜…

Linux基础-Makefile的编写、以及编写第一个Linux程序:进度条(模拟在 方便下载的同时,更新图形化界面)

目录 一、Linux项目自动化构建工具-make/Makefile ​编辑 背景&#xff1a; makefile小技巧&#xff1a; 二、Linux第一个小程序&#xff0d;进度条 先导&#xff1a; 1.如何利用/r,fflush(stdout)来实现我们想要的效果&#xff1b; 2.写一个倒计时&#xff1a; 进度条…

c++ 红黑树(带头结点)

想必在看到这篇文章的时候&#xff0c;你一定是带着问题去搜索的&#xff0c;一定是对红黑树已经有了初步大致的认识&#xff0c;已经知道了红黑树的性质与普通红黑树的功能与如何代码实现&#xff0c;但是莫一天突然看到了带头结点的红黑树&#xff0c;肯定是对此有一些疑惑的…

匹配行最大值替换为最小值公式

好的!我们一步一步详细讲解这个公式的作用和如何实现你想要的功能。 ### 数据结构假设: - 你的数据在 A、B、C 列中,每一行都有值。 - 需要在 A 列和 B 列相同的行中,找到 C 列中的最大值,将其替换为最小值,其他值保持不变。 ### 公式: ```excel =IF(C2=MAX(IF(($A$2:$…

Clickhouse使用笔记

clickhouse官方文档&#xff1a;https://clickhouse.com/docs/zh/sql-reference/data-types/decimal 一&#xff0c;建表 create table acitivity_user_record ( id String DEFAULT generateUUIDv4(), -- 主键自增 activityId String, userId String, userName Nullable(Strin…

Git之误执行git rm -r解决方案(六十七)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

9月16日星期一今日早报简报微语报早读

9月16日星期一&#xff0c;农历八月十四&#xff0c;早报微语早读。 1、猫眼专业版数据&#xff1a;2024年中秋档票房破亿&#xff1b; 2、WTT澳门冠军赛&#xff1a;孙颖莎夺得女单冠军&#xff1b; 3、乐山夹江县&#xff1a;支持农村居民进城购房&#xff0c;每户补贴5万…

天融信把桌面explorer.exe删了,导致开机之后无windows桌面,只能看到鼠标解决方法

win10开机进入桌面&#xff0c;发现桌面无了&#xff0c;但是可以ctrlaltdelete调出任务管理器 用管理员权限打开cmd&#xff0c;输入&#xff1a; sfc /scanfilec:\windowslexplorer.exe 在运行C:\windows\Explorer.exe&#xff1b;可以进入桌面&#xff0c;但是隔离几秒钟…

Java多线程1

目录 1.简述进程与线程之间的主要差异。 2.描述进程间通信的常用方式。 3.详细说明线程间如何进行通信。 4.什么是原子性&#xff1f;请举例说明。 5.i 和 i--操作是否具有原子性&#xff1f;为什么&#xff1f; 1.简述进程与线程之间的主要差异。 进程和线程是计算机系统…

MYSQL基础-多表操作-事务-索引

1. 多表设计 概述 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a; …

Python3时间模块使用

文章目录 python安装时间处理模块概述time 模块常用方法 datetime 模块常用方法 时间戳与 datetime 的相互转换时区处理使用 pytz 设置时区 实际应用场景日志时间处理时间差计算不同时区的时间转换 结论 在 Python 编程中&#xff0c;时间处理和时间格式转换是非常常见的需求&a…

美团图床设置教程

大厂图床&#xff0c;CDN加速 项目地址&#xff1a;https://github.com/woniu336/mt-img 使用方法 在mt.php填上你的token即可&#xff0c;然后打开index.html上传图片 获取token方法 注册https://czz.meituan.com/发布视频&#xff0c;上传封面&#xff0c;注意在上传封面后…

【退役之再次线上部署】Spring Boot + VUE + Nginx + MySQL

这篇博客写在凌晨 4 点 20 分&#xff0c;这个时候我刚线上部署完成 web 项目&#xff0c;自己写的全栈项目 这个点儿&#xff0c;也睡不着了&#xff0c;索性就写篇博客记录一下 一、踩坑实录 这个是 最重要的&#xff0c;所以写在前面 Nginx 配置文件 location location /a…

【更新】上市公司-供应链金融水平数据(2000-2023年)

上市公司供应链金融是指上市公司利用其产业链核心地位&#xff0c;通过整合金融资源&#xff0c;为供应链上下游企业提供包括融资、结算、风险管理等在内的综合金融服务。为了衡量上市公司的供应链金融水平&#xff0c;参考周兰等&#xff08;2022&#xff09;的研究方法&#…

基于Spring Boot的心理健康服务系统的设计与实现(毕业论文)

目    录 1 前言 1 1.1 研究目的与意义 1 1.2 国内外研究现状 1 1.3 论文结构 3 2 可行性分析 3 3 系统需求分析 4 3.1 用户需求分析 4 3.2 心理咨询师需求分析 5 3.3 管理员需求分析 6 3.4 业务流程分析 7 4 概要设计 9 4.1 系统结构设计 10 4.2 功能模块设计 10 4.2.1 管…

20Kg载重30分钟续航多旋翼无人机技术详解

一、机架与结构设计 1. 材料选择&#xff1a;为了确保无人机能够承载20Kg的负载&#xff0c;同时实现30分钟的续航&#xff0c;其机架材料需选用轻质高强度的材料&#xff0c;如碳纤维或铝合金。这些材料不仅具有良好的承重能力&#xff0c;还能有效减轻无人机的整体重量&…

计算机毕业设计Python深度学习垃圾邮件分类检测系统 朴素贝叶斯算法 机器学习 人工智能 数据可视化 大数据毕业设计 Python爬虫 知识图谱 文本分类

基于朴素贝叶斯的邮件分类系统设计 摘要&#xff1a;为了解决垃圾邮件导致邮件通信质量被污染、占用邮箱存储空间、伪装正常邮件进行钓鱼或诈骗以及邮件分类问题。应用Python、Sklearn、Echarts技术和Flask、Lay-UI框架&#xff0c;使用MySQL作为系统数据库&#xff0c;设计并实…

Gitlab 中几种不同的认证机制(Access Tokens,SSH Keys,Deploy Tokens,Deploy Keys)

前言 公司主要使用 Go 语言做项目&#xff0c;有一些 Gitlab 私有仓库需要引用&#xff0c;在做 CI 时&#xff0c;要自行配置权限以获取代码。 最近发现各个项目组在做 CI 遇到仓库权限问题时的解决方式不尽相同&#xff0c;有用 Project Token 的&#xff0c;有用 Deploy K…

unity3d入门教程五

unity3d入门教程五 13鼠标事件处理13.2鼠标跟随13.3鼠标拖拽&#xff08;选中对象&#xff0c;拖动对象&#xff09;13.4几个问题14.1事件函数14.2脚本的执行顺序14.3脚本的参数14.4引用类型的参数&#xff08;进行图片更换&#xff0c;人物换装&#xff09; 13鼠标事件处理 需…

自由流转--实例

一、自由流转的形态 流转能力打破设备界限&#xff0c;多设备联动&#xff0c;使用户应用程序可分可合、可流转&#xff0c;实现如邮件跨设备编辑、多设备协同健身、多屏游戏等分布式业务。 二、跨端迁移 在应用开发层面&#xff0c;跨端迁移指在A端运行的UIAbility迁移到B端上…