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

运行结果:

二、引用的地址

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

运行结果:

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

三、引用就是别名常量

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

运行结果:

四、引用对象

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

运行结果:

五、空引用

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

六、按值传递

# 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并没有改变。

七、按址传递

# 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的值,而不是他们的副本。

运行结果:

八、按别名传递

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

运行结果:

九、利用指针返回多值

# 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所指向的内存区域中的值来实现的。

十、利用引用来返回多值

以上程序用引用更为方便

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

运行结果:

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

时间: 2024-08-23 07:48:45

C++ 引用(1)的相关文章

.net 工程中引用出现感叹号

在工程中引用出现感叹号,有两个原因 原因1:  这是由于之前引用的Dll文件不见了. 右键有感叹号的项,然后选择 "属性" 里边有一个路径属性 这个路径就是之前这个Dll文件的路径,现在这个文件不在了,你需要找到现在这个文件的路径 右键有感叹号的项,然后选择"移除" 右键"引用",选择添加引用,然后选择那个不在的dll的真实路径 其他的项用相同的方式处理 原因2:可能是引用的.Net版本高于了当前工程的.Net版本 更改所引用的工程文件的.Net

C# 动态生成WebService,无需添加引用

C#项目调用WebService是很常见的现象,但一旦修改链接地址就需要重新更新引用很是麻烦,这里跟大家分享一个通过地址,无需添加引用动态生成Webservice的小方法 方法类: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.ServiceModel; 6 using System.ServiceModel.Channels

C++学习笔记----2.4 C++引用在本质上是什么,它和指针到底有什么区别

从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量). 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值.值传递过程中,被调

DLL引用摘录

最近使用DllImport,从网上google后发现,大部分内容都是相同,又从MSDN中搜集下,现将内容汇总,与大家分享. 大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功能呢?答案是肯定的,大家可以通过C#中的DllImport直接调用这些功能. DllImport是System.Runtime.InteropServices命名空间下的一个属性

PHP中引用类的属性

在一个类中,可以访问一个特殊的指针--$this.如果当前类的一个属性为$attribute,则当在该类中通过一个操作设置或访问该变量时,可以使用$this->attribute来引用. class classname { public $attribute; function operation($param) { $this->attibute = $param echo $this->attribute; } }

使用软引用和弱引用防止内存溢出

下面以使用软引用为例来详细说明.弱引用的使用方式与软引用是类似的. 假设我们的应用会用到大量的默认图片,比如应用中有默认的头像,默认游戏图标等等,这些图片很多地方会用到.如果每次都去读取图片,由于读取文件需要硬件操作,速度较慢,会导致性能较低.所以我们考虑将图片缓存起来,需要的时候直接从内存中读取.但是,由于图片占用内存空间比较大,缓存很多图片需要很多的内存,就可能比较容易发生OutOfMemory异常.这时,我们可以考虑使用软引用技术来避免这个问题发生. 首先定义一个HashMap,保存软引用

引用传递

引用传递的本质就在于别名,而这个别名只不过是放在了栈内存之中,既:一块堆内存可以被对个栈内存所指向 举例: Person per1 = new Person(); per1.name = "小于子"; per1.age = 30; Person2 oper2 = per1; oper2.name = "狗剩"; 在程序开发中,所谓的垃圾空间指的是没有任何栈内存指向的堆内存空间,所有的垃圾空间将不定期被java的垃圾收集器(GC.Garbage Collector)进

this的引用

每个对象都可以使用this关键字引用本身.如果一个类的方法需要访问该类本身的成员变量或其他方法,就应该使用this,其实在引用的学习中我们已经接触到额this的引用,只不过那时不懂,在我们使用引用的时候,我们没有显示地添加this引用,呢么编译器会自动的为 我们添加上,我们尅将this应用作为参数给一个方法,通过这种方式一个对象可以将它本身的引用传给其他对象. 如果一个构造器用this关键字来调用本类中的其他构造器,那么这个this语句必须是本构造器的第一行否则,会产生一个编译错误.在Java中

Android中的WeakReference 弱引用

WeakReference 弱引用 定义:弱引用,与强引用(我们常见的引用方式)相对:特点是:GC在回收时会忽略掉弱引用对象(忽略掉这种引用关系),即:就算弱引用指向了某个对象,但只要该对象没有被强引用指向,该对象也会被GC检查时回收掉. 强引用实例自然不会被GC回收! 如何引出弱引用?弱引用的实际用途是什么? 什么是内存泄漏?Java使用有向图机制,通过GC自动检查内存中的对象:如果GC发现一个或一组对象为不可达的状态,则将该对象从内存中回收.也就是说:一个对象不被任何引用所指向,则该对象会在

MVC,MVP 和 MVVM 的图示 引用地址(http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html)

分类: 开发者手册 MVC,MVP 和 MVVM 的图示 作者: 阮一峰 日期: 2015年2月 1日 复杂的软件必须有清晰合理的架构,否则无法开发和维护. MVC(Model-View-Controller)是最常见的软件架构之一,业界有着广泛应用.它本身很容易理解,但是要讲清楚,它与衍生的 MVP 和 MVVM 架构的区别就不容易了. 昨天晚上,我读了<Scaling Isomorphic Javascript Code>,突然意识到,它们的区别非常简单.我用几段话,就可以说清. (题图: