首页 > 编程语言 >c++领域展开第二幕——入门基础(引用的概念和使用以及和指针的区别)超详细!!!!

c++领域展开第二幕——入门基础(引用的概念和使用以及和指针的区别)超详细!!!!

时间:2024-12-07 14:28:25浏览次数:8  
标签:const rs int c++ 第二幕 对象 引用 指针

在这里插入图片描述

文章目录

前言

上一篇学习了c++入门的一些基础部分语法,今天还有基础中最重要的一部分——引用
对的,没错,今天只有一个内容就是——引用。
引用之后就正式开始类和对象啦

一、引用

1.1 引用的概念和定义

引用不是新定义一个变量,而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;

在这里插入图片描述
在这里插入图片描述

类型& 引用别名 = 引用对象;

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;
}

在这里插入图片描述

1.2 引用的特性

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

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	// 编译报错:“ra”:  必须初始化引用
	//int& ra;
	int& b = a;
	int c = 20;
	// 这里并非让b引用c,因为C++引用不能改变指向,
	// 这里是一个赋值
	b = c;
	cout << &a << endl;
	cout << &b << endl;
	cout << &c << endl;
	return 0;
}

1.3 引用的使用

• 引用在实践中主要是用于:引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
引用传参跟指针传参功能是类似的,引用传参相对更方便一些
• 引用返回值的场景相对比较复杂,我们在这里简单讲了一下场景。
• 引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向Java的引用可以改变指向

void Swap(int& rx, int& ry)
{
	int tmp = rx;
	rx = ry;
	ry = tmp;
}
int main()
{
	int x = 0, y = 1;
	cout << x <<" " << y << endl;
	Swap(x, y);
	cout << x << " " << y << endl;
	return 0;
}

这里的swap函数就不用像以前那样传指针写,直接传引用,改变的是实参

再来看看以前学过的数据结构的代码,把指针改成引用

#include<iostream>
using namespace std;
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void STInit(ST& rs, int n = 4)
{
	rs.a = (STDataType*)malloc(n * sizeof(STDataType));
	rs.top = 0;
	rs.capacity = n;
}
// 栈顶
void STPush(ST& rs, STDataType x)
{
	assert(ps);
	// 满了, 扩容
	if (rs.top == rs.capacity)
	{
		printf("扩容\n");
		int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
		STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity *
		sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		rs.a = tmp;
		rs.capacity = newcapacity;
	}
	rs.a[rs.top] = x;
	rs.top++;
}
// int STTop(ST& rs)
int& STTop(ST& rs)   //  这里用了引用做返回  正常返回值时形参是拷贝的内容 不能对原本的内容进行修改
{						//  但是传引用的话,传的是参数的别名,能直接修改实参    
	assert(rs.top > 0);
	return rs.a[rs.top];
}
int main()
{
	// 调用全局的
	ST st1;
	STInit(st1);
	STPush(st1, 1);
	STPush(st1, 2);
	cout << STTop(st1) << endl;
	STTop(st1) += 10;
	cout << STTop(st1) << endl;
	return 0;
}
#include<iostream>
using namespace std;
typedef struct SeqList
{
	int a[10];
	int size;
}SLT;
void SeqPushBack(SLT& sl, int x)
{}
typedef struct ListNode
{
	int val;
	struct ListNode* next;
}LTNode, *PNode;
// 指针变量也可以取别名,这里LTNode*& phead就是给指针变量取别名
// 这样就不需要用二级指针了,相对而言简化了程序
//void ListPushBack(LTNode** phead, int x)
//void ListPushBack(LTNode*& phead, int x)
void ListPushBack(PNode& phead, int x)
{
	PNode newnode = (PNode)malloc(sizeof(LTNode));
	newnode->val = x;
	newnode->next = NULL;
	if (phead == NULL)
	{
		phead = newnode;
	}
	else
	{
		//...
	}
}
int main()
{
	PNode plist = NULL;
	ListPushBack(plist, 1);
	return 0;
}

可以看到,传引用还是相对于传指针要方便很多
在类和对象的学习中,引用可就是必不可少的一部分,不然小编也不会整整一篇文章围绕引用

1.4 const 引用

可以引用一个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。
• 不过需要注意的是类似int& rb = a3; double d = 12.34; int& rd = d; 这样一些场景下a3的和结果保存在一个临时对象中, int& rd = d 也是类似,在类型转换中会产生临时对象存储中间值,也就是说rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就触发了权限放大,必须要用常引用才可以。
• 所谓临时对象就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象,C++中把这个未命名对象叫做临时对象。

看看代码更好理解

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	const int& ra = 30;
	// 编译报错: “初始化”: 无法从“int”转换为“int &”
	// int& rb = a * 3;
	const int& rb = a*3;
	double d = 12.34;
	// 编译报错:“初始化”: 无法从“double”转换为“int &”
	// int& rd = d;
	const int& rd = d;
	return 0;
}
int main()
{
	const int a = 10;
	// 编译报错: “初始化”: 无法从“const int”转换为“int &”
	// 这里的引用是对a访问权限的放大
	//int& ra = a;
	// 这样才可以
	const int& ra = a;
	// 编译报错: “ra”: 不能给常量赋值
	//ra++;
	// 这里的引用是对b访问权限的缩小
	int b = 20;
	const int& rb = b;
	// 编译报错:error C3892: “rb”: 不能给常量赋值
	//rb++;
	return 0;
}

1.5 指针和引用的关系

C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。
• 语法概念上引用是一个变量的取别名不开空间指针是存储一个变量地址,要开空间
• 引用在定义时必须初始化指针建议初始化,但是语法上不是必须的
• 引用在初始化时引用一个对象后就不能再引用其他对象而指针可以在不断地改变指向对象
• 引用可以直接访问指向对象,指针需要解引用才是访问指向对象
• sizeof中含义不同**,引用结果为引用类型的大小**,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte)
指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全一些


总结

从引用的概念和定义到使用再到const引用,最后的引用与指针的区别
深刻理解到引用和指针的差别,引用的用处还是很多的
再后序的类和对象学习当中会经常用到,不要走开,小编持续更新中~~~~

在这里插入图片描述

标签:const,rs,int,c++,第二幕,对象,引用,指针
From: https://blog.csdn.net/daily_233/article/details/144308772

相关文章

  • 接龙数列(第十四届蓝桥杯C++B组JAVA题解 动态规划)
    对于一个长度为 KK 的整数数列:A1,A2,...,AK,我们称之为接龙数列当且仅当 Ai 的首位数字恰好等于 Ai−1 的末位数字(2≤i≤K)。例如 12,23,35,56,61,11是接龙数列;12,23,34,56不是接龙数列,因为 56的首位数字不等于 3434 的末位数字。所有长度为 11 的整数数列都......
  • 异常--C++
    文章目录一、异常的概念及使用1、异常的概念2、异常的抛出和捕获3、栈展开4、查找匹配的处理代码5、异常重新抛出6、异常安全问题7、异常规范二、标准库的异常一、异常的概念及使用1、异常的概念异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行......
  • 打卡信奥刷题(375)用C++信奥B3618[普及组/提高] 寻找团伙
    寻找团伙题目描述世界局势风云变幻,你想办一件大事。办事自然要有人参与,你能从nnn个人里面挑选一部分人共襄盛举。要办这件事,一共涉及......
  • c++ 中异步闲谈:async,await,future, promise的使用和注意事项
    《C++异步妙韵》C++异步展新章,async开启并行航。函数异步去闯荡,不必同步苦守望。future犹如希望光,异步结果有处藏。等待之时心不慌,获取成果见真章。promise把诺来担当,结果设定不迷茫。与future紧捆绑,异步流程稳起航。await恰似静候郎,future前面来......
  • 跟我学C++中级篇——数据类型转换的思考
    一、数据类型的转换可以这样说,几乎所有的开发者都必须经历这种数据类型转换导致的异常的痛苦。不管是C还是C++的开发者,这都是一个必须经历的过程。在多线程开发的早期,传入线程的就是一个void*的指针,然后在线程函数内部自己再做相应的类型转换。有过因此导致线程崩溃的开发......
  • C++天使的灵动心跳代码:类和对象(中上)
    文章目录1.类的六大默认成员函数2.构造函数2.1默认构造函数2.2显式调用构造函数3.析构函数3.1默认析构函数3.2显式调用析构函数希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力!本篇将介绍类和对象中的重点部分,六大函数中的前四个尤为重要,所以......
  • 【C++算法】31.前缀和_连续数组
    文章目录题目链接:题目描述:解法C++算法代码:图解题目链接:525.连续数组题目描述:解法前缀和思想:如果把0变成-1,那么就是在区间内找一个最长的子数组,使得子数组中所有元素的和为0前面做过一个前缀和为k的子数组,这里就是转化为和为0。前缀和+哈希表哈希表里......
  • 【C++算法】32.前缀和_矩阵区域和
    文章目录题目链接:题目描述:解法C++算法代码:题目链接:1314.矩阵区域和题目描述:解法防止有人看不明白题目,先解释一下题目二维前缀和思想:使用前缀和矩阵ret=[x1,y1]~[x2,y2]=D=(A+B+C+D)-(A+B)-(A+C)+A=dp[x2,y2]-dp[x1-1,y2]-dp[x2,y1-1]+dp[x......
  • 指针初步学习(四)
    指针数组和多重指针什么是指针数组 一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。定义一维指针数组的一般形式为类型名*数组名[数组长度];int*p[4];指针数组比较适合用来指向若干个字符串,使字符......
  • 用一篇博文带你了解c++和python两种编程语言到底有什么区别?
      成长路上不孤单......