【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配置文件 // 爬取图片…

Linux下Mysql的小版本升级

1、查看当前 MySQL 版本 [rooticoolkj bin]# cd /usr/local/mysql/bin [rooticoolkj bin]# ./mysql -V ./mysql Ver 8.0.30 for Linux on x86_64 (MySQL Community Server - GPL) 2、 查看系统版本 [rooticoolkj bin]# lsb_release -a LSB Version: :core-4.1-amd64:cor…

索引概述(一)

1. 索引是啥&#xff1f; 在关系数据库中&#xff0c;索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构。可以比喻为目录&#xff0c;能快速定位到对应章节。 2. 索引目的 加快查询速度。 3. 有哪些索引&#xff1f; 单列索引 组合索引 4. 索…

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

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

fastjson和httpclient的基本使用

fastjson alibaba的fastjson来处理对象首先fastjson主要有两类对象 JSONObject JSONObject对象&#xff0c;可以看做是一个Object对象 JSONObject jsonObject new JSONObject(); jsonObject.put("username","admin"); jsonObject.put("password&…

阿里十年 “帕鲁” 手把手带你学习 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;}…

现浇混凝土与后浇混凝土的区别与优缺点比较

现浇混凝土与后浇混凝土的区别与优缺点比较 一、现浇混凝土 现浇混凝土又称“同步浇筑混凝土”&#xff0c;是指在混凝土模板安装完成后&#xff0c;直接将混凝土灌入到模板中浇筑成型的过程。现浇混凝土的特点是施工成功率高、周期短、工程质量好&#xff0c;因此广泛应用于…

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

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

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

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

【链表】-Lc206-反转链表(三大指针)

写在前面 最近想复习一下数据结构与算法相关的内容&#xff0c;找一些题来做一做。如有更好思路&#xff0c;欢迎指正。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.代码 写在后面 一、场景描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反…

PAM4(4 级脉冲幅度调制)

PAM4 正文简介PAM4 的优势 正文 简介 全称 pulse-amplitude modulation 4 level。PAM4 是一个多级信号调制&#xff0c;它使用四种不同的信号等级&#xff0c;分别为 0&#xff0c;1&#xff0c;2&#xff0c;3。每一个信号等级可以表示 2 比特的逻辑信息。 PAM4 的优势 在…

14.java集合

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