C++ 引用

1、什么是引用?

# include<iostream>
using namespace std;
int main()
{
	int num;
	int &mum=num;
	//这就好像李四有个外号叫李大嘴,大家称呼李四指的是李四这个人,称呼李大嘴也是指的是李四这个人,李四和李大嘴都是一个人,只是名字不同而已。
    //对num的操作也就是对mum的操作,&mum不是取地址符,而是引用符号。他们的符号相同,但是功能不同。应用就是别名。
	num=999;
	cout<<"num的值为:"<<num<<endl;
	cout<<"mum的值为:"<<mum<<endl;
	num=100;
    cout<<"num的值为:"<<num<<endl;
	cout<<"mum的值为:"<<mum<<endl;
	return 0;
}

运行结果:


2、引用的地址

# include<iostream>
using namespace std;
int main()
{
	int a;
	int &ra=a;
	cout<<"a的地址为:"<<&a<<endl;
	cout<<"ra的地址为:"<<&ra<<endl;
	return 0;
}

运行结果:


注释:因此对ra的操作就是对a的操作。因为他们的地址是一样的。

3、引用就是别名常量

# include<iostream>
using namespace std;
int main()
{
	int a;
	int &ra=a;
	a=555;
	cout<<"a的地址为:"<<&a<<endl;
	cout<<"ra的地址为:"<<&ra<<endl;
    cout<<"a的值为:"<<a<<endl;
	cout<<"ra的值为:"<<ra<<endl;
	int b=999;
	ra=b;
	cout<<"a的地址为:"<<&a<<endl;
	cout<<"ra的地址为:"<<&ra<<endl;
	cout<<"b的地址为:"<<&b<<endl;
	cout<<"a的值为:"<<a<<endl;
	cout<<"ra的值为:"<<ra<<endl;
	cout<<"b的值为:"<<b<<endl;
	//把b的值付给ra,那么a和ra的值都给改变了,但是地址并没有变化。
	ra=100;
    cout<<"a的值为:"<<a<<endl;
	cout<<"ra的值为:"<<ra<<endl;
	cout<<"b的值为:"<<b<<endl;
	//a和ra的值又便换来了。
	//在这个实例中,我们将ra定义为a的值,ra只是属于a,但是他不会因为b而变成b的别名,但是他会因为b的赋值,把变量a也变成b的值。
	//ra是a的别名,我们不能改变,但是我们却可以改变ra的值,这样还会导致a的值得改变。
	return 0;
}
运行结果:

4、引用对象

# include<iostream>
using namespace std;
class Human
{
public:
	int get(){return i;}
	void set(int x){i=x;}
private:
	int i;
};
int main()
{
	Human Mike;
	Human &rMike=Mike;
	//对象的别名
	//Human &rHuman=Human;
	//以上是错误的,我们不能定义类的引用。Human是一个类,他们有具体的内存地址,我们不能定义一个类的引用。
	rMike.set(123);
	cout<<rMike.get()<<endl;
	//以上看来,rMike是和MIke一样的。
	return 0;
}

运行结果:

5、空引用

我们知道指针进行删除操作后,需要将它们赋为空,引用却不需要这么做,这是因为引用是原来对象的别名,假如该对象存放在栈中,那么在对象超出作用域时别名会和对象一起消失。假如该对象存放在堆中,由于堆中内存空间必须使用指针来访问,因此用不着别名,即使再定义一个该指针的别名,那么将指针删除并赋空之后,该指针的别名中的地址也相应的赋空了。

6、按值传递


# include<iostream>
using namespace std;
void swap(int a,int b)
{
	int c;
	cout<<"swap函数中,交换前,a:"<<a<<"\t"<<"b:"<<b<<endl;
	c=a;
	a=b;
	b=c;
	cout<<"swap函数中,交换后,a:"<<a<<"\t"<<"b:"<<b<<endl;
}
int main()
{
	int a=3,b=4;
	cout<<"主程序中,交换前,a:"<<a<<"\t"<<"b:"<<b<<endl;
	swap(a,b);
    cout<<"主程序中,交换后,a:"<<a<<"\t"<<"b:"<<b<<endl;
	return 0;
}

运行结果:


注释:

以上这个问题很简单,swap函数交换的是main函数中a和b的副本的值;也就是说在main函数中定义的a和b的备份的值;swap函数交换的是main函数中的a和b的副本,而不是a和b本身;这是因为当我们直接将a和b传递给swap函数时,这样的传递是按值传递;假如将a和b按值传递给swap函数,那么编译器会自动在栈中创建a和b的拷贝,然后将a和b的拷贝传递给swap函数。在swap函数中对a和b的拷贝进行交换。因此我们看到的输出语句,a和b确实进行了交换,只不过交换的是a和b的副本。由于交换的是a和b的副本,并不是a和b本身,所以在swap函数结束后,输出的值显示main函数中的a和b并没有改变。

7、按址传递

# include<iostream>
using namespace std;
void swap(int *a,int *b)
{
	int c;
	//以下是交换主函数中a和b的值,所以要带*。
	cout<<"swap函数中,交换前,a:"<<*a<<"\t"<<"b:"<<*b<<endl;
	c=*a;
	*a=*b;
	*b=c;
	cout<<"swap函数中,交换后,a:"<<*a<<"\t"<<"b:"<<*b<<endl;
}
int main()
{
	int a=3,b=4;
	cout<<"主程序中,交换前,a:"<<a<<"\t"<<"b:"<<b<<endl;
	swap(&a,&b);
	//传递的是a和b的地址。
    cout<<"主程序中,交换后,a:"<<a<<"\t"<<"b:"<<b<<endl;
	return 0;
}
//通过地址的传递,我们能直接访问到a和b的地址,因此修改的也是a和b的值,而不是他们的副本。

运行结果:


8、按别名传递

# include<iostream>
using namespace std;
void swap(int &a,int &b)
//这里的a和b不是主函数中的a和b,这里的a和b是主函数a和b的别名,传递的是主函数中a和b中的别名,这个比址传递还要简单。
//通过a和b的别名可以交换a和b的值。
{
	int c;
	cout<<"swap函数中,交换前,a:"<<a<<"\t"<<"b:"<<b<<endl;
	c=a;
	a=b;
	b=c;
	cout<<"swap函数中,交换后,a:"<<a<<"\t"<<"b:"<<b<<endl;
}
int main()
{
	int a=3,b=4;
	cout<<"主程序中,交换前,a:"<<a<<"\t"<<"b:"<<b<<endl;
	swap(a,b);
    cout<<"主程序中,交换后,a:"<<a<<"\t"<<"b:"<<b<<endl;
	return 0;
}

运行结果:


9、利用指针返回多值

# include<iostream>
using namespace std;
int func(int a,int *b,int *c);
int main()
{
	int a=1,b=2,c=3;
	cout<<"主程序,调用func函数前...\n";
	cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
	func(a,&b,&c);
	cout<<"主程序,调用func函数后...\n";
	cout<<"a:"<<a<<endl<<"b:"<<b<<endl<<"c:"<<c<<endl;
	//a是值传递,b和c是地址传递
	return 0;
}
int func(int a,int *b,int *c)
{
	cout<<"func函数中,计算前...\n";
	cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
	a=a+1;
	*b=(*b)*(*b);
	//用过b的地址传递,把b的值平方再付给b
	*c=(*c)*(*c)*(*c);
	cout<<"a:"<<a<<endl<<"b:"<<*b<<endl<<"c:"<<*c<<endl;
	return a;
}

运行结果:


虽然是返回了a值,但是我们可以到是返回了3个值,因为b和c的值也改变了。

我们可以把a看作是返回的判断值,b和c看做运算的返回值。

用该方法我们可以实现汇报执行程序时的非法操作信息。

# include<iostream>
using namespace std;
int func(int a,int *b,int *c);
int main()
{
	int a,b,c;
	int check;
	cout<<"请您输入要进行运算的数字,";
	cout<<"您输入的数字将作为园的半径和正方形的边长:";
	cin>>a;
	check=func(a,&b,&c);
	if(check)
	{
		cout<<"输入的数字超过计算范围!\n";
	}
	else
	{
		cout<<"圆的面积为:"<<b<<endl;
		cout<<"正方形的面积为:"<<c<<endl;
	}
	return 0;
}
int func(int a,int *b,int *c)
{
    if(a>20000)
	{
		a=1;
	}
	else
	{
		*b=a*a*3.14;
		*c=a*a;
		a=0;
	}
	return a;
}

运行结果:


但是我们要注意的是:这两个值不是通过返回机制来得到实现的,而是通过改变函数指针参量*b和*c所指向的内存区域中的值来实现的。

10、利用引用来返回多值

以上程序用引用更为方便

# include<iostream>
using namespace std;
int func(int a,int &b,int &c);
int main()
{
	int a,b,c;
	int check;
	cout<<"请您输入要进行运算的数字,";
	cout<<"您输入的数字将作为园的半径和正方形的边长:";
	cin>>a;
	check=func(a,b,c);
	if(check)
	{
		cout<<"输入的数字超过计算范围!\n";
	}
	else
	{
		cout<<"圆的面积为:"<<b<<endl;
		cout<<"正方形的面积为:"<<c<<endl;
	}
	return 0;
}
int func(int a,int &b,int &c)
{
    if(a>20000)
	{
		a=1;
	}
	else
	{
		b=a*a*3.14;
		c=a*a;
		a=0;
	}
	return a;
}

运行结果:


由此看出 ,引用更为方便!

15、到底是使用指针还是引用

既然引用实现了指针的功能,并且使用起来更加方便,那么为什么还要使用指针呢?

(1)这是因为指针可以为空,但是引用不能为空;指针可以被赋值,但是引用只可以被初始化,不可以被赋予另一个对象的别名。如果你想使用一个变量记录不同对象的地址,那么必须使用指针。

#include<iostream>
using namespace std;
int main()
{
	int *p;  
	int i=8;
	p=&i;
	int j=9;
	p=&j;
	//以上程序是正确的,p可以保存i的地址,也可以保存j的地址。
    //int x=1,y=2;
	//int &a=x;
	//&a=y;
	//由于引用只能被初始化,a既然是x的别名,那么他不可能是别的变量的别名了。
    return 0;
}

(2)在堆中创建一块内存区域,必须要用指针来指向它,否则该区域就会变成无法访问的内存空间。当然我们也可以使用引用来引用指向内存空间的指针。

#include<iostream>
using namespace std;
int main()
{
	int *p=new int;
	int &r=*p;
	//r就是p指针指向处的值的别名,我们可以通过r来修改保存在new int中的数据。
	r=4;
	//4就会自动的保存到new int 中。
	cout<<"锥中空间存放的数据:"<<r<<endl;
	//int &t=new int;
	//以上代码是错误的。
    //但是我们必须要明白,我们不可以用引用来指向堆中新建的空间,因为引用只是个别名,他不可以当做指针来使用。
	cout<<"锥中空间存放的数据:"<<*p<<endl;
	return 0;
}
运行结果:


#include<iostream>
using namespace std;
int main()
{
	int *&r=new int;
	//r其实可以看做一个指针,它与该语句是相同的,int *p=new int;
	//我们一般不会那么使用的,知道就行。
	*r=3;
	cout<<r<<endl;
	return 0;
}

运行结果:

#include<iostream>
using namespace std;
int main()
{
	int *p=new int;
	//定义了一个指向int 的指针p,该指针指向新建的一块内存。
	if(p!=NULL)
    //如果不为空,表示内存创建成功。
	{
		int &r=*p;
		r=3;
		cout<<r<<endl;
	}
	return 0;
}

运行结果:

指针和引用的区别:

指针可以为空,引用不能为空;

指针可以被赋值,引用不能被赋值;

指针可以指向堆中的空间,引用不能指向堆中的空间。


16、指针和引用可以一快使用

#include<iostream>
using namespace std;
int main()
{
	int *func(int &one,int *two,int x);
	//该函数声明了一个func函数,里面有三个参数,第一个为int型变量的别名,第二个为int型变量的指针two,第三个为整形参数x,返回一个指向int 变量的指针.
	int *p,i;
	//定义了一个指针变量p和一个int型数据i。
	return 0;
}

17、引用容易犯的错误


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值