【C++】C++入门基础讲解(二)

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

导读

接着上一篇的内容继续学习,今天我们需要重点学习引用。

1. 引用

在C++中,引用是一种特殊的变量,用于别名一个已经存在的对象或变量。通过引用,可以使用别名来操作原始对象,而不是创建一个新的副本。
引用提供了一种简洁和高效的方式来传递参数、返回值和修改变量的值。

1.1 引用特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}
int main()
{TestRef();return 0;
}

在这里插入图片描述

上述代码我们可以发现两者的地址是相同的,a和r指向是完全一样的
注意:
引用类型必须和引用实体是同种类型的

1.2 做参数使用

引用作为函数参数,意味着在函数调用时,我们将一个变量的引用传递给函数。这样,函数可以直接操作原始变量,而不是对其进行拷贝。

void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}int main() {int x = 10;int& ref = x; // 引用xcout << "x = " << x << endl;   // 输出: x = 10cout << "ref = " << ref << endl; // 输出: ref = 10ref = 20; // 修改ref,实际上是修改xcout << "x = " << x << endl;   // 输出: x = 20cout << "ref = " << ref << endl; // 输出: ref = 20int a = 5;int b = 10;swap(a, b); // 传递a和b的引用,修改原始变量cout << "a = " << a << endl;   // 输出: a = 10cout << "b = " << b << endl;   // 输出: b = 5return 0;
}

在这里插入图片描述

1.3 做返回值使用

函数返回引用时需要确保返回的引用仍然指向有效的内存空间。通常,可以返回类成员变量的引用、静态变量的引用、函数内静态局部变量的引用等。
同时要注意的是,返回引用时需要避免返回对局部变量的引用,因为局部变量在函数结束后会被销毁,返回对其引用可能会导致未定义行为。

int& Max(int& a, int& b)
{return (a > b) ? a : b;
}int main()
{int x = 10, y = 20;int& max = Max(x, y);max = 30;  // 修改了y的值cout << "y: " << y << endl;  // 输出: 30return 0;
}

在这里插入图片描述
我们再来看一下下面的代码:

int& Add(int a, int b)
{int c = a + b;return c;
}
int main()
{int& ret1 = Add(1, 2);int& ret2 = Add(3, 4);cout << "Add(1, 2) is :" << ret1 << endl;cout << "Add(3, 4) is :" << ret2 << endl;return 0;
}

按照我们的预期,我们输出的两个数应该是3和7,然而:
在这里插入图片描述
这是为什么呢?

在函数 Add 中,局部变量 c 的生命周期仅限于函数内部。
当函数执行完毕后,c 被销毁,而返回的引用 ret 将指向一个不存在的对象。
当再次使用这个引用时,就会出现未定义的行为。

因此,应该避免将局部变量作为返回值的引用类型返回

1.4 引用和指针的区别

  1. 指针使用*来定义,而引用使用&来定义。
int* ptr; // 声明一个指针
int& ref = *ptr; // 定义一个引用,引用指针所指向的变量
  1. 指针可以被初始化为null或指向任意变量的地址,而引用必须在声明时初始化,并且不能为null。
int* ptr = nullptr; // 指针为空
int x = 5;
int& ref = x; // 引用x,ref指向x的地址
  1. 指针可以被重新赋值为指向其他变量的地址,而引用一旦初始化后就不能重新赋值为引用其他变量。
int x = 5;
int y = 10;
int* ptr = &x; // ptr指向x的地址
ptr = &y; // ptr现在指向y的地址int& ref = x; // ref引用x
ref = y; // 修改了x的值,ref仍然引用x
  1. 指针可以为空指针,即指向空地址,而引用不可以为空。
int* ptr = nullptr; // 指针为空
int& ref; // 错误,引用必须初始化
  1. 有多级指针,但是没有多级引用

1. 5 const引用

常引用可以引用普通变量,可以引用常变量,可以引用字面变量。
我们来看下面示例:

常变量:

const int a = 10;
int& ra = a;		// 错误
const int& ra = a;	//正确

int& ra = a; 试图将 a 绑定到一个非常引用 ra 上,这是错误的。常量对象不能通过非常引用进行修改。
因此这里应该使用 const int& ra = a; 来将 a 绑定到一个常引用 ra 上。

字面值:

int& b = 10;		// 错误
const int& b = 10;	// 正确

int& b = 10; 试图将字面值 10 绑定到一个非常引用 b 上,这是错误的。字面值是一个临时值,不能通过非常引用进行修改。
正确的做法应该是将 b 声明为常引用: const int& b = 10;

类型转换:

double d = 12.34;
int& rd = d;			// 错误
const double& rd = d;	// 正确

int& rd = d; 试图将 d 绑定到一个非常引用 rd 上,这是错误的。
d 是一个 double 类型的变量,不能通过非常引用来绑定到 int 类型的引用上。
正确的做法是将 rd 声明为 const 引用: const double& rd = d;

将 const 修饰符用于 int 类型的引用,可以确保在引用对象上不会进行修改操作,保护对象的不可变性,避免意外的修改导致数据不一致或错误的计算结果。

常引用的声明方式与普通引用相同,只是在引用类型前添加const关键字。常引用主要用于函数参数传递和对象成员访问,以确保访问的对象不会被修改。

void Print(const int& value) 
{// value 为 const 引用,不能修改其值cout << "Value: " << value << endl;// value = 10;  // 错误,不能修改 const 引用的值
}int main() 
{int num = 5;Print(num);  // 传递 num 的值给 printValue 函数return 0;
}

2. 内联函数

以inline修饰的函数叫做内联函数,是C++中的一种函数,它的定义和调用都被嵌入到调用该函数的地方,而不是通过函数调用的机制进行调用,没有函数调用建立栈帧的开销。
内联函数的主要目的是为了提高函数的执行效率,减少函数调用的开销。

inline int add(int a, int b) {return a + b;
}
int main()
{int ret = add(10, 20);return 0;
}

内联函数的使用有以下几点需要注意:

  1. 内联函数应该比较短小,避免过长的函数体,因为内联函数的定义会被嵌入到调用处,过长的函数体会导致代码冗长。

  2. 内联函数适合用于频繁执行的函数,例如在循环中反复调用的函数。

  3. 内联函数不能包含复杂的控制流语句,例如循环或递归,因为内联函数的展开是通过复制代码来实现的,这样的代码会导致代码膨胀。

  4. 编译器对内联函数的展开是有一定的自由度的,它可以根据实际情况决定是否展开函数体,因此对于内联函数的定义和使用应该在同一个文件中,以便编译器能够进行函数体的展开。

3. auto关键字

auto关键字是C++中的一个关键字,用于声明变量时自动推导变量的类型。
使用auto关键字可以省略变量类型的声明,编译器会根据变量的初始化表达式推导出变量的类型。
例如:

auto a = 10; // a的类型为int 
auto b = 3.14; // b的类型为double 
auto c = "hello"; // c的类型为const char*

使用auto关键字可以使代码更加简洁和易读,特别是当变量的类型较为复杂或者不确定时,auto关键字可以减少类型声明的冗余。

注意:
auto关键字在编译器推导类型时是静态的,即编译时就确定了类型,无法在运行时动态改变变量的类型。

auto与指针和引用结合起来使用:

当auto与指针和引用结合使用时,auto会推导出指针或引用的类型。

int x = 10;
auto *ptr = &x; // ptr的类型为int*float y = 3.14;
auto *ptr2 = &y; // ptr2的类型为float*

使用auto声明引用类型变量示例:

int x = 10;
auto &ret = x; // ref的类型为int&float y = 3.14;
auto &ret2 = y; // ref2的类型为float&

4. 基于范围的for循环

基于范围的for循环是一种简化的循环结构,用于遍历一个序列(如字符串、列表、元组等)中的每个元素。

语法形式如下:

for 变量 in 序列: 循环体

变量表示当前迭代的元素,序列表示需要遍历的序列,循环体表示需要执行的操作。
我们常用下面的这种方式来遍历数组:

int main()
{int arr[] = { 1, 2, 3, 4, 5 };for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)arr[i] *= 2;for (int* p = arr; p < arr + sizeof(arr) / sizeof(arr[0]); ++p)cout << *p << endl;return 0;
}

今天我们来看范围for的使用。

int main()
{int arr[] = { 1, 2, 3, 4, 5 };for (auto& e : arr)e *= 2;for (auto e : arr)cout << e << " ";return 0;
}

注意:

  1. for循环迭代的范围必须是确定的
  2. 迭代的对象要实现++和==的操作。

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

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

相关文章

【遥感专题系列】影像信息提取之—— 土地利用数据监督与非监督分类

基于光谱的影像的分类可分为监督与非监督分类&#xff0c;这类分类方法适合于中低分辨率的数据&#xff0c;根据其原理有基于传统统计分析的、基于神经网络的、基于模式识别的等。 本专题以ENVI5.3及以上版本的监督与非监督分类的实际操作为例&#xff0c;介绍这两种分类方法的…

什么是NAT?NAT类型有哪些?

晚上好&#xff0c;我的网工朋友。NAT是一种地址转换技术&#xff0c;它可以将IP数据报文头中的IP地址转换为另一个IP地址&#xff0c;并通过转换端口号达到地址重用的目的。 在大多数网络环境中&#xff0c;我们都需要通过 NAT 来访问 Internet。 NAT作为一种缓解IPv4公网地址…

如何搭建Nextcloud云存储网盘并实现无公网ip访问本地文件【内网穿透】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

双非本科准备秋招(9.2)——力扣哈希

1、383. 赎金信 跟昨天的题大同小异&#xff0c;因为只有26个字母&#xff0c;所以可以建个有26个坑位的数组。 做完昨天的题目&#xff0c;这个题没啥新意。 class Solution {public boolean canConstruct(String ransomNote, String magazine) {int[] hashTable new int[…

从0开始搭建若依微服务项目 RuoYi-Cloud(保姆式教程 一)

掌握陌生项目解读技巧 掌握若依(RuoYi-Cloud)框架 掌握SpringCloud Alibaba体系项目开发套路&#xff0c;结合我之前所有企业项目来学习就知道有多么简单。 一、框架介绍 1. 简介 一直想做一款后台管理系统&#xff0c;看了很多优秀的开源项目但是发现没有合适的。于是利用空…

Python中如何将字符串变成数字?

字符串和数字是Python中常见的数据类型&#xff0c;而且在撰写Python程序的时候&#xff0c;也经常会遇到需要将字符串转换为数字的情况&#xff0c;那么Python中如何将字符串变成数字?有多种方法可以使用&#xff0c;接下来一起来看看具体内容介绍。 1、使用int()函数 int(…

使用 Node.js 和 Cheerio 爬取网站图片

写一个关于图片爬取的小案例 爬取效果 使用插件如下&#xff1a; {"dependencies": {"axios": "^1.6.0","cheerio": "^1.0.0-rc.12","request": "^2.88.2"} }新建一个config.js配置文件 // 爬取图片…

Git 教程 | 将本地修改后的文件推送到 Github 指定远程分支上

Git 是一种分布式版本控制系统&#xff0c;用于敏捷高效地处理任何大小的项目。它是由 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的开源版本控制软件。Git 的本地克隆就是一个完整的版本控制存储库&#xff0c;无论脱机还是远程都能轻松工作。开发人员会在本地提交其工…

阿里十年 “帕鲁” 手把手带你学习 Java 常见并发容器

阿里十年 “帕鲁” 手把手带你学习 Java 常见并发容器 文章目录 阿里十年 “帕鲁” 手把手带你学习 Java 常见并发容器ConcurrentHashMapCopyOnWriteArrayListConcurrentLinkedQueueBlockingQueueBlockingQueue 简介ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueu…

计算机设计大赛 推荐系统设计与实现 协同过滤推荐算法

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 推荐系统设计与实现 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1…

PyTorch2ONNX-分类模型:速度比较(固定维度、动态维度)、精度比较

图像分类模型部署: PyTorch -> ONNX 1. 模型部署介绍 1.1 人工智能开发部署全流程 #mermaid-svg-bAJun9u4XeSykIbg {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bAJun9u4XeSykIbg .error-icon{fill:#552222;}…

2023量子科技十大用例 | 光子盒年度系列

随着量子科技的不断突破&#xff0c;量子计算、量子通信、量子测量等应用场景逐渐向纵深拓展&#xff0c;量子产业呈现出较好的发展势头。 量子计算的发展比以往任何时候都更加迅速&#xff0c;这提醒我们&#xff0c;这项看似‘高冷’的前沿科技&#xff0c;已悄然应用于不少领…

使用IconFont实现矢量图标(Avalonia)

使用IconFont实现矢量图标(Avalonia) IconFont可以自己在阿里图标库收藏好&#xff0c;然后打包下载&#xff0c;这个就不在这里进行描述了&#xff0c;如果不知道怎么生成图标项目以及打包下载&#xff0c;可以先自己百度。 App.axaml中进行载入 <Application.Resources…

14.java集合

文章目录 概念Collection 接口概念示例 Iterator 迭代器基本操作&#xff1a;并发修改异常增强循环遍历数组&#xff1a;遍历集合&#xff1a;遍历字符串&#xff1a;限制 list接口ListIteratorArrayList创建 ArrayList&#xff1a;添加元素&#xff1a;获取元素&#xff1a;修…

八、MySQL事务和SQL优化

1 什么是事务 Transaction&#xff0c;使我们数据库内最小且不可再分的单元。通常一个事务对应一个完整的业务(例如银行账户转账业务&#xff0c;该业务就是一个最小的工作单元)。一个完整的业务需要批量的DML(INSERT 、UPDATE、DELETE)语句共同联合完成。事务只和DML语句有关…

Js设计模式

1、简介 设计模式总的来说是一个抽象的概念&#xff0c;是软件开发人员在开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。 2、工厂模式 工厂模式是用来创建对象的一种最常用的设计模式。我们不暴露创建对…

计算机设计大赛 基于图像识别的跌倒检测算法

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于图像识别的跌倒检测算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…

金融行业现场故障处理实录

KL银行现场服务记录—HA故障 服务时间 2019年9月10日星期二 14&#xff1a;40 到2019年9月11日星期三 0&#xff1a;30 服务内容 排查redhat RHEL 6.4 一个节点cman启动故障。 &#xff08;1&#xff09;、查看系统日志&#xff1b; &#xff08;2&#xff09;、查看ha日志…

跟着pink老师前端入门教程-day13

品优购案例 一、品优购项目规划 1. 品优购项目整体介绍 项目名称&#xff1a;品优购 项目描述&#xff1a;品优购是一个电商网站&#xff0c;我们要完成 PC 端首页、列表页、注册页面的制作 2. 品优购项目学习目的 1. 电商类网站比较综合&#xff0c;里面需要大量的布…

如何使用Python Flask搭建一个web页面并实现远程访问

文章目录 前言1. 安装部署Flask并制作SayHello问答界面2. 安装Cpolar内网穿透3. 配置Flask的问答界面公网访问地址4. 公网远程访问Flask的问答界面 前言 Flask是一个Python编写的Web微框架&#xff0c;让我们可以使用Python语言快速实现一个网站或Web服务&#xff0c;本期教程…