您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

c++引用详解

时间:2022-02-25 11:05:31  来源:  作者:小羊的Debug

铺垫:

变量名实质上是一段连续存储空间的别名,是一个标号

程序中通过变量来申请并命名内存空间

通过变量的名字可以使用存储空间

(能不能再名字的基础上在起个名字?)

概念:

1) 可以看做一个已定义变量的别名

引用是c++的语法范畴,不能再用C语言的思想去思考问题(间接修改)

属于c++编译器对c的扩展

 

引用做函数参数

普通引用在声明时必须用其他的变量进行初始化

引用作为函数参数声明时不进行初始化

#include<IOStream>
using namespace std;
//引用基本用法
void mAIn()
{
	
	int a = 10;
	int &b = a;
	b = 100;
	printf("b:%dn", b);
	printf("a:%dn", a);
	cout << "hello...." << endl;
	system("pause");
	return;
}
void main11()
{
	int a = 10;
	int &b = a;
	//int &c;  //普通引用必须要初始化
	system("pause");
}
void myswap01(int a, int b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
void myswap02(int *a,int *b)
{
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}
void myswap03(int &a, int &b)
{
	int c = 0;
	c = a;
	a = b;
	b = c;
}
void  main()
{
	int x, y;
	x = 10;
	y = 20;
	myswap01(x, y);
	printf("x:%d,y:%dn", x, y);
	myswap02(&x, &y);
	printf("x:%d,y:%dn", x, y);
	myswap03(x, y);
	printf("x:%d,y:%dn", x, y);
	system("pause");
}
//复杂数据类型 的引用
struct Teacher
{
	char name[64];
	int  age;
};
void printfT(Teacher *pT)
{
	cout << pT->age << endl;

}
//pT是t1的别名,相当于修改了t1
void printfT2(Teacher &pT)
{
	cout << pT.age << endl;

}
//pT和t1是两个不同的变量
void printfT3(Teacher pT)
{
	cout << pT.age << endl;
pT.age=45;//只会修改pT变量,不会修改t1变量
}
void main()
{
	Teacher t1;
	t1.age = 35;
	printfT(&t1);
	printfT2(t1);//pT是t1的别名
  printfT3(t1);//pT是形参,t1拷贝了一份数据,给pT
  printf("t1.age:%dn",t1.age);
	cout << "hello...." << endl;
	system("pause");
	return;
}

引用的意义

引用作为其他指针变量的别名而存在,因此在一些场合可以替代指针

引用相对于指针来说具有更好的可读性和实用性

引用的本质

c++编译器背后做了什么工作

单独定义的时候必须初始化--->很像常量

1)引用在c++内部实现是一个常指针

2)c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占的空间与指针相同

3)从使用的角度,引用会让人误会其只是一个别名,没有自己的储存空间,这是c++为了实用性做出的细节隐藏.

结论:当我们使用引用的语法时,我们不用去关心编译器引用是怎么做了

当我们分析奇怪的语法现象时,才去考虑编译器是怎么做的

#include<iostream>
using namespace std;
void main01()
{
	const int c1 = 10;
	int a = 10;
	int &b = a;//像常量
	printf("&a:%dn", &a);
	printf("&b:%dn", &b);//a b就是同一块内存空间的门牌号   依附于这个内存空间
	cout << "hello.." << endl;
	system("pause");
	return;
}
//普通引用有自己的空间吗?-->有,和指针所占的一样
struct Teacher
{
	char name[64];//64
	int age;//4
	int &a;//4
	int &b;//4
};
//引用的本质一个常量指针
void main()
{
	printf("sizeof(Teacher):%dn", sizeof(Teacher);
	system("pause");
}

void  modifyA(int &a1)
{
	a1 = 100;
}
void  modifyA2(int* const a1)
{
	*a1 = 10;//*实参的地址,去间接修改实参的值
}
void main()
{
	int a = 10;
	modifyA(a);//指向这个函数调用的时候,我们程序员不需要取a的地址
	printf("a:%dn", a);

	modifyA2(&a);//如果是指针 需要我们手工去取实参地址
	printf("sizeof(Teacher):%dn", sizeof(Teacher));
	system("pause");
}

//间接赋值
//间接赋值成立的三个条件
/*
1 定义2个变量
2 建立关系  实参取地址传给形参
3 形参间接修改实参的值
*/
void  modifyA3(int *p)
{
	*p = 190;//3
}
void main()
{
	int a = 10;
	int *p = NULL; //1
	p = &a;
	*p = 100;
	{
		*p = 200;
	}
	modifyA3(&a);//2
}
//引用是间接赋值哪几个条件的组合?     2编译器做了
//1   23后2个条件写在一起了         只不过2编译器做了

函数返回值是引用(引用当左值)

c++引用使用时的难点:

当函数返回值为引用时,

若返回栈变量,不能成为其他引用的初始值,不能作为左值使用

若返回静态变量或全局变量 可以成为其他引用的初始值.

即可作为右值使用,也可作为左值使用

#include<iostream>
using namespace std;
int getAA1()
{
	int a;
	a = 10;
	return a;
}
//返回a的本身
int& getAA2()
{
	int a;
	a = 10;
	return a;
}
int* getAA3()
{
	int a;
	a = 10;
	return &a;
}

void main01()
{
	int a1 = 0;
	int a2 = 0;
	a1 = getAA1();
	a2 = getAA2();
	int &a3= getAA2();
	printf("a1:%dn", a1);
	printf("a2:%dn", a2);
	printf("a3:%dn", a3);
	cout << "hello.." << endl;
	system("pause");
	return;
}
//返回静态/全局
int j()
{
	static int a = 10;
	a++;
	return a;
}
int &j()
{
	static int a = 10;
	a++;
	return a;

}
void main()
{
	int a1 = 10;
	int a2 = 20;
	a1 = j1();
	a2 = j2();
	int &a3 = j2();
	printf("a1:%dn", a1);
	printf("a2:%dn", a2);
	printf("a3:%dn", a3);
	cout << "hello.." << endl;
	system("pause");
	return;

}
//函数当左值 
//返回变量的值
int g()
{
	static int a = 10;
	a++;
	return a;
}
//返回变量本身
int &g()
{
	static int a = 10;
	a++;
	return a;
}
void main()
{
	//g1() = 100;//执行这个,函数返回值就是11.不成立err
	g2() = 100;//把上面的函数改成了100,所以这个就成立

	system("pause");
}

指针的引用

#include<iostream>
using namespace std;
struct Teacher
{
	char name[64];
	int age;

};
int getTeacher(Teacher **p)
{
	Teacher *tmp = NULL;
	if (p == NULL)
	{
		return -1;
	}
	tmp = (Teacher*)malloc(sizeof(Teacher));
	if (tmp == NULL)
	{
		return -2;
	}
	p->age = 33;
	*p = tmp;
}
//指针的引用做函数参数
int getTeacher2(Teacher* &myp)
{//给myp赋值相当于给主函数中的pT1赋值
	myp = (Teacher*)malloc(sizeof(Teacher));
	if (myp == NULL)
	{
		return -1;
	}
	p->age = 36;
}
void FreeTeacher(Teacher *pT1)
{
	if (pT1 == NULL)
	{
		return;
	}
	free(pT1);
}
void main()
{
	Teacher *pT1 = NULL;
	getTeacher(&pT1);//二级指针
	cout << "age:" << pT1->age << endl;
	FreeTeacher(pT1);

	getTeacher2(pT1);//引用
	cout << "age:" << pT1->age << endl;
	FreeTeacher(pT1);
	cout << "hello.." << endl;
	system("pause");
	return;
}

c++中的const常量

可能分配内存空间,也可能不分配

当const常量为全局,并且需要在其他文件中使用,会分配空间

在使用&操作符,取const常量的地址,会分配

当const修饰引用,会分配

#include<iostream>
using namespace std;

void main()
{
	int x = 20;
	const int &y = x;//常引用  让变量拥有只读属性 不同通过y去修改x了
	//常引用初始化分为2种情况//1)用变量 初始化 常引用
	{
		int x1 = 30;
		const int &y1 = x1;
	
	}
	//2)用字面量 初始化 常引用
	{
		const int a = 40;
		int &m = 41;//普通引用 引用一个字面量
		//字面量有没有内存地址?-->没有

	}
	cout << "hello.." << endl;
	system("pause");
	return;
}

结论:

const &int e==const int* const e

普通引用==int const e

当使用常量对const引用进行初始化时,编译器会为常量值分配空间,并用引用名作为这段空间的别名

使用字面量对const引用初始化后,将生成一个只读变量



Tags:c++   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  Search: c++  点击:(8)  评论:(0)  加入收藏
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  Search: c++  点击:(7)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25  Search: c++  点击:(7)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  Search: c++  点击:(27)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03  Search: c++  点击:(73)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  Search: c++  点击:(121)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  Search: c++  点击:(122)  评论:(0)  加入收藏
指针变量在C/C++中的内存占用
在编程领域,尤其是C和C++这类底层语言中,指针是一个核心概念,它允许程序直接操作内存地址。然而,关于指针本身在内存中占用的空间大小,却常常让初学者感到困惑。本文将深入探讨这...【详细内容】
2024-01-09  Search: c++  点击:(101)  评论:(0)  加入收藏
C++的面向对象编程:深入解析与理解
当我们谈论C++时,面向对象编程(OOP)是一个无法回避的话题。那么,C++的面向对象究竟是什么?为什么它如此重要?本文将从基本概念到实际应用,为您详细解析C++中的面向对象编程。一、面...【详细内容】
2024-01-03  Search: c++  点击:(99)  评论:(0)  加入收藏
有什么好用的C/C++源代码混淆工具?
开始使用ipaguard前言iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP...【详细内容】
2023-12-29  Search: c++  点击:(122)  评论:(0)  加入收藏
▌简易百科推荐
C++中的外部模板及其在当前编译文件中的实例化
在C++中,模板是一种泛型编程的工具,它允许程序员以一种类型无关的方式编写代码。然而,模板的一个常见问题是它们会导致编译时间增加,特别是在大型项目中,当多个源文件包含相同的...【详细内容】
2024-04-11  鲨鱼编程  微信公众号  Tags:C++   点击:(8)  评论:(0)  加入收藏
C++常见避坑指南
C++ 从入门到放弃?本文主要总结了在C++开发或review过程中常见易出错点做了归纳总结,希望借此能增进大家对C++的了解,减少编程出错,提升工作效率,也可以作为C++开发的避坑攻略。...【详细内容】
2024-04-03  腾讯技术工程    Tags:C++   点击:(7)  评论:(0)  加入收藏
C++ 之父反驳白宫警告:自诞生第一天起,C++ 的目标就一直是提高安全性
整理 | 郑丽媛上个月,美国白宫国家网络主任办公室(ONCD)在一份主题为《回到基础构件:通往安全软件之路》的 19 页 PDF 报告中,呼吁开发人员停止使用容易出现内存安全漏洞的编程语...【详细内容】
2024-03-25    CSDN  Tags:C++   点击:(7)  评论:(0)  加入收藏
八个 C++ 开源项目,帮助初学者进阶成长
通过参与或阅读开源项目的源代码,你可以获得丰富的实践机会。实际的项目代码比简单的教程更具挑战性,可以帮助你深入理解 C++ 的各种概念和技术。1.ThreadPool一个简单的 C++1...【详细内容】
2024-03-22  AI让生活更美好  微信公众号  Tags:C++   点击:(27)  评论:(0)  加入收藏
C# 中15个值得收藏的开源项目推荐
在开源的世界里,C# 编程语言也占有一席之地。这些开源项目涵盖了多个领域,从框架、库到工具,它们为C#开发者提供了丰富的资源和工具,帮助他们更高效地开发、测试和部署应用程序...【详细内容】
2024-03-20  程序员编程日记  微信公众号  Tags:C#   点击:(33)  评论:(0)  加入收藏
C#异步编程:Task.Run vs. async-await,掌握基础与高级用法
概述:C#中的异步编程有两主要方式:Task.Run用于在后台线程执行同步操作,而async-await更适用于清晰表达异步流程。基础用法展示了它们的简单应用,高级用法则演示了它们的结合使...【详细内容】
2024-03-09  架构师老卢  今日头条  Tags:C#   点击:(32)  评论:(0)  加入收藏
C++多线程编程:解锁性能与并发的奥秘
今天我们将深入探讨C++中的多线程编程,揭示多线程如何解锁性能潜力,提高程序的并发性能。什么是多线程?在计算机科学中,多线程是指一个进程(程序的执行实例)中的多个线程同时执行...【详细内容】
2024-02-03     AI让生活更美好  Tags:C++   点击:(73)  评论:(0)  加入收藏
C++代码优化攻略
今天我们将深入探讨C++性能优化的世界。在当今软件开发的浪潮中,高性能的代码是必不可少的。无论是开发桌面应用、移动应用,还是嵌入式系统,性能都是关键。1. 选择合适的数据结...【详细内容】
2024-01-26  AI让生活更美好  微信公众号  Tags:C++   点击:(121)  评论:(0)  加入收藏
C# 线程本地存储为什么线程间值不一样
为什么用 ThreadStatic 标记的字段,只有第一个线程拿到了初始值,其他线程都是默认值,让我能不能帮他解答一下,尼玛,我也不是神仙什么都懂,既然问了,那我试着帮他解答一下,也给后面类...【详细内容】
2024-01-26  一线码农聊技术  微信公众号  Tags:C#   点击:(74)  评论:(0)  加入收藏
C++质数检测器的设计与实现​
质数,作为数学中的一个基本概念,一直以其独特的性质吸引着众多研究者和爱好者。质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。在实际应用中,质数检测也扮演着...【详细内容】
2024-01-15  鲨鱼编程  微信公众号  Tags:C++   点击:(122)  评论:(0)  加入收藏
站内最新
站内热门
站内头条