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

news2024/11/17 12:59:56

💗个人主页💗
⭐个人专栏——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; // 引用x

    cout << "x = " << x << endl;   // 输出: x = 10
    cout << "ref = " << ref << endl; // 输出: ref = 10

    ref = 20; // 修改ref,实际上是修改x

    cout << "x = " << x << endl;   // 输出: x = 20
    cout << "ref = " << ref << endl; // 输出: ref = 20

    int a = 5;
    int b = 10;
    swap(a, b); // 传递a和b的引用,修改原始变量

    cout << "a = " << a << endl;   // 输出: a = 10
    cout << "b = " << b << endl;   // 输出: b = 5

    return 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;  // 输出: 30

    return 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.coloradmin.cn/o/1418074.html

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

相关文章

成都直播产业园解析直播供应链金融服务,天府锋巢直播产业基地打造“金融+产业+生态”新型模式

天府锋巢直播产业基地如何打造“金融产业生态”新型模式&#xff1f; 本文将为您全面解析基地提供的成都直播产业园供应链金融服务 锋巢资讯&#xff5e;每周准时报道&#xff5e;&#xff5e; 赶紧下拉&#xff0c;阅读全文 Q:企业入驻园区能获得哪些直播供应链金融服务&…

如何注册海外苹果账号下载软件?

国内的苹果Appstore有严格的上线审查&#xff0c;导致很多软件不支持。只能通过海外的苹果账号登录后下载。 比如chatgpt还有加密资产的大部分软件。 其实自己注册一个很简单。 一、注册国内Apple ID 打开苹果官网&#xff0c;https://appleid.apple.com 注册一个中国区的A…

【机器学习】正则化

正则化是防止模型过拟合的方法&#xff0c;它通过对模型的权重进行约束来控制模型的复杂度。 正则化在损失函数中引入模型复杂度指标&#xff0c;利用给W加权值&#xff0c;弱化了数据的噪声&#xff0c;一般不正则化b。 loss(y^,y)&#xff1a;模型中所有参数的损失函数&…

【代码审计】小白友好的根据CNVD审计BEESCMS

BEESCMS源码下载 目录 ①BEESCMS后台登录存在SQL注入漏洞(CNVD-2020-62375) ②BEESCMS存在任意文件删除漏洞(CNVD-2020-33193) ③BEESCMS存在文件上传漏洞(CNVD-2018-18082) ④BEESCMS企业网站管理系统存在文件包含漏洞(CNVD-2020-64781) ①BEESCMS后台登录存在SQL注入漏洞…

Python接口自动化框架设计到开发

1.如何设计一个接口自动化测试框架 根据接口地址、接口类型、请求数据、预期结果来进行设计&#xff0c;对于需要登录后才能进行操作的接口那么则需要进行header cookie等数据的传递&#xff0c;自动化测试的难点就是数据依赖。 2.python操作excel获得内容 首先python操作exce…

SSL加密证书免费申请

首先&#xff0c;让我们来了解一下SSL证书的基本作用。SSL证书通过公钥和私钥的非对称加密技术&#xff0c;使得服务器与浏览器之间的通信内容得到高强度加密&#xff0c;同时验证网站的真实身份&#xff0c;从而提升用户的信任度&#xff0c;也是搜索引擎排名优化的一个重要因…

JSP和JSTL板块:第一节 JSP追根溯源 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 JSP和JSTL&#xff1a;第一节 JSP主要内容 一、什么是JSP二、IDEA的JSP相关配置1.UTF-8编码2.JSP代码模板 三、JSP的底层是Servlet四、Jsp的注释1.显式注释2.隐式注释 五、Scriptlet : 写在Jsp里的java脚本段 一、什么是JSP JSP: Java Server Page。SUN 公司提供的动态…

C语言实现快速排序算法(附带源代码)

快速排序 在区间中随机挑选一个元素作基准&#xff0c;将小于基准的元素放在基准之前&#xff0c;大于基准的元素放在基准之后&#xff0c;再分别对小数区与大数区进行排序。 动态效果过程演示&#xff1a; 快速排序&#xff08;Quick Sort&#xff09;是一种常用的排序算法&…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-3 getBoundingClientRect()

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>getBoundingClientRect()</title> </head> <script>function getRect(){var obj document.getElementById(example); //获取元素对象var objR…

路灯哪个牌子好?五款好用新年台灯推荐

自从娃进入小学&#xff0c;学习和视力是群里妈妈们永远不变的两大话题&#xff0c;特别是视力话题&#xff0c;常常能炸出“深潜”已久的爸爸们加入讨论。最近这几年&#xff0c;孩子的近视率又提高了&#xff01;根据国家卫健委的报道&#xff0c;儿童青少年近视总体发生率高…

Walrus 0.5发布:重构交互流程,打造开箱即用的部署体验

开源应用管理平台 Walrus 0.5 已于近日正式发布&#xff01; Walrus 0.4 引入了全新应用模型&#xff0c;极大程度减少了重复的配置工作&#xff0c;并为研发团队屏蔽了云原生及基础设施的复杂度。Walrus 0.5 在这一基础上&#xff0c;通过重构交互流程、增强抽象能力&#xff…

COW AI接入到微信 保姆教程 (部署在服务器,插件安装)

此文章不涉及国外的AI模型&#xff0c;也无需翻墙&#xff0c;跟某AI模型无关&#xff0c;审核大哥别弄错了 最近的AI开始越开越火了&#xff0c;开始介入到我们生活中的方方面面。就有人好奇AI是否能接入到微信吗&#xff1f;我在GitHub上搜索的时候还真有除了对话外还可以通…

编译Opencv3.3 版本遇到的Cuda版本变更导致:CUDA_nppicom_LIBRARY (ADVANCED)链接找不到的问题根本解法:

前言&#xff1a; Opencv 开源库的使用是必须的&#xff0c;但是&#xff0c;开源项目的特性&#xff0c;造成&#xff0c;版本的依赖性比较复杂&#xff0c; 尤其是针对某一款老硬件的SDK&#xff0c;往往随着某个开源库的使用&#xff0c;导致&#xff0c;无法编译的问题&am…

Windows XP x86 sp3 安装 Python3.4.4

1 下载 Python3.4.4&#xff0c;下载地址&#xff0c;点击红色部分。 Python Release Python 3.4.4 | Python.org 2 一路 Next&#xff0c;将 C:\Python34 和 C:\Python34\Scripts 加入环境变量。 3 python 查看版本&#xff0c;python -m pip list 查看安装的包。 4 其他(打…

关东升老师Python著作推荐(由电子工业出版社出版)

前言&#xff1a;关东升老师简单介绍 一个在IT领域摸爬滚打20多年的老程序员、软件架构师、高级培训讲师、IT作家。熟悉Java、Kotlin、Python、iOS、Android、游戏开发、数据库开发与设计、软件架构设计等多种IT技术。参与设计和开发北京市公交一卡通百亿级大型项目&#xff0c…

OpenAI、斯坦福大学提出Meta-Prompting,有效提升语言模型的性能

为了研究如何提高语言模型的性能&#xff0c;使其更充分有效地输出对于提问的回答&#xff0c;来自斯坦福和 OpenAI 的学者强强联手&#xff0c;通过提出一种名为元提示&#xff08;meta-prompting&#xff09;的方法来深入探索。元提示通过让单个语言模型&#xff08;如 GPT-4…

微信小程序(二十二)获取全局实例

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.全局实例的定义位置 2.全局实例中数据的修改方法 源码&#xff1a; app.js App({//数据可以包括在第二级globalData:{userInfo:null,token:1243,userInfo:null},//globalData并不是关键词&#xff0c;数据可以…

TCP_拥塞控制

引言 24年春节马上就要到了&#xff0c;作为开车党&#xff0c;最大的期盼就是顺利回家过年不要堵车。梦想是美好的&#xff0c;但现实是骨感的&#xff0c;拥堵的道路让人苦不堪言。 在网络世界中&#xff0c;类似于堵车的问题也存在&#xff0c;而TCP&#xff08;Transmissi…

智慧矿山数字孪生三维可视化平台,赋能矿业新型工业化数字化转型

智慧矿山数字孪生三维可视化平台&#xff0c;赋能矿业新型工业化数字化转型。随着科技的不断发展&#xff0c;数字化转型已经成为各行各业发展的必然趋势。矿业作为传统产业&#xff0c;也需要紧跟时代步伐&#xff0c;通过数字化转型实现更加高效、安全和环保的生产方式。智慧…

STM32_JTAG引脚及复用代码

目录 1.JTAG引脚1.1 说明&#xff08;可以不看&#xff09;1.2 引脚 2.复用代码3. 手册介绍&#xff08;可以不看&#xff09; 总是忘记有些引脚是JTAG复用的&#xff0c;导致偶尔浪费一些时间&#xff0c;记录一下。 1.JTAG引脚 1.1 说明&#xff08;可以不看&#xff09; …