【C++】——引用与指针的比较

引用从表层来看就是内存单元的别名。从底层来看,和指针处理相同,也开辟内存,在用到引用变量的地方系统会自动解引用。一般初学者很容易把引用和指针混淆一起,但他们并不一样。

int m;      //m是被引用物
int &n=m;   //n是m的一个引用

n 相当于 m 的别名(绰号),对 n 的任何操作就是对 m 的操作。例如有人名叫王小 毛,他的绰号是“三毛”。说“三毛”怎么怎么的,其实就是对王小毛说三道四。所以 n 既不是 m 的拷贝,也不是指向 m 的指针,其实 n 就是 m 它自己。 

引用和指针的区别如下:

(1)引用被创建的同时必须被初始化,指针则可以在任何时候被初始化 。

(2)不能有 NULL 引用,引用必须与合法的存储单元关联,指针则可以是 NULL。

(3)一旦引用被初始化,就不能改变引用的关系,指针则可以随时改变所指的对象 。

int i = 5; 
int j = 6;  
int &k = i;  
k = j; // k 和 i 的值都变成了 6; 

(4)指针可以有多级,但是引用只能是一级。

int **p;   //合法 
int &&a;   //不合法的

(5)"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小。

(6)指针和引用的自增(++)运算意义不一样,对引用的操作直接反应到所指向的对象,而不是改变指向;而对指针的操作,会使指针指向下一个对象,而不是改变所指对象的内容。

#include<iostream>  
using namespace std;  
  
int main(int argc,char** argv)  
{  
int i=10;  
int& ref=i;  
ref++;  
  
cout<<"i="<<i<<endl;       //11
cout<<"ref="<<ref<<endl;   //11
  
int j=20;  
ref=j;  
ref++;  
  
cout<<"i="<<i<<endl;      //21
cout<<"ref="<<ref<<endl;  //21
cout<<"j="<<j<<endl;      //20
return 0;  
}  

对ref的++操作是直接反应到所指变量之上,对引用变量ref重新赋值"ref=j",并不会改变ref的指向,它仍然指向的是i,而不是j。理所当然,这时对ref进行++操作不会影响到j。而这些换做是指针的话,情况大不相同。

(7)const对指针和引用的限定是有差别的。

第一点 :常量指针VS常量引用

常量指针:指向常量的指针,在指针定义语句的类型前加const,表示指向的对象是常量。定义指向常量的指针只限制指针的间接访问操作,而不能规定指针指向的值本身的操作规定性。常量指针定义"const int* pointer=&a"告诉编译器,*pointer是常量,不能将*pointer作为左值进行操作。

常量引用:指向常量的引用,在引用定义语句的类型前加const,表示指向的对象是常量。也跟指针一样不能利用引用对指向的变量进行重新赋值操作。 

第二点:指针常量VS引用常量

在指针定义语句的指针名前加const,表示指针本身是常量。在定义指针常量时必须初始化!而这是引用天生具来的属性,不用再引用指针定义语句的引用名前加const。

指针常量定义"int* const pointer=&b"告诉编译器,pointer是常量,不能作为左值进行操作,但是允许修改间接访问值,即*pointer可以修改。

第三点:常量指针常量VS常量引用常量

  常量指针常量:指向常量的指针常量,可以定义一个指向常量的指针常量,它必须在定义时初始化。常量指针常量定义"const int* const pointer=&c"告诉编译器,pointer和*pointer都是常量,他们都不能作为左值进行操作。

       而就不存在所谓的"常量引用常量",因为跟上面讲的一样引用变量就是引用常量。C++不区分变量的const引用和const变量的引用。程序决不能给引用本身重新赋值,使他指向另一个变量,因此引用总是const的。如果对引用应用关键字const,起作用就是使其目标称为const变量。即没有:Const double const& a=1;只有const double& a=1;

引用的主要功能是传递函数的参数和返回值。

C++语言中,函数的参数和返回值的传递方式有三种:值传递、 指针传递和引用传递。 

(1)“值传递”:

# include<iostream>

using namespace std;

void Func1(int x)
{
	x=x+10;
}

int main()
{
	int n=0;
	Func1(n);
	cout<<"n="<<n<<endl;    //n=0
	return 0;
}

由于 Func1 函数体内的 x 是外部变量 n 的一份拷贝, 改变 x 的值不会影响 n, 所以 n 的值仍然是 0。 

(2)“指针传递”:

# include<iostream>

using namespace std;

void Func2(int *x)
{
	(*x)=(*x)+10;
}

int main()
{
	int n=0;
	Func2(&n);
	cout<<"n="<<n<<endl;   //n=10
	return 0;
}

由于 Func2 函数体内的 x 是指向外部变量 n 的指 针,改变该指针的内容将导致 n 的值改变,所以 n 的值成为 10。 

(3)"引用传递“:

# include<iostream>

using namespace std;

void Func3(int &x)
{
	x=x+10;
}

int main()
{
	int n=0;
	Func2(n);
	cout<<"n="<<n<<endl;   //n=10
	return 0;
}

由于 Func3 函数体内的 x 是外部变量 n 的引用,x 和 n 是同一个东西,改变 x 等于改变 n,所以 n 的值成为 10。 

对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式像“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用” 这东西? 答案是“用适当的工具做恰如其分的工作” 。  指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。 就像一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用? 如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”, 以免发生意外。比如说,某人需要一份证明,本来在文件上盖上公章的印子就行了,如 果把取公章的钥匙交给他,那么他就获得了不该有的权利。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值