指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名,引用初始化后不能改变指向。使用时,引用更加安全,指针更加灵活。
1 非空区别
在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。不存在指向空值的引用这个事实意味着引用的代码效率比使用指针高。(引用和指针指向一个对象时,引用的创建和销毁不会调用类的拷贝构造函数和析构函数。delete一个指针会调用该对象的析构函数,注意防止二次析构。)
2 可修改区别
指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。
3 合法性区别
在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。引用必须初始化,指针可以不必初始化。
4 引用、指针与const。
存在常量指针和常量引用指针,表示指向的对象是常量,不能通过指针或者常量修改常量;存在指针常量,不存在引用常量,因为引用本身不能修改指向的特性和与指针常量的特性相同,不需要引用常量。
5 应用区别
总的来说,在以下情况下应该使用指针:一是考虑到存在不指向任何对象的可能(在这种情况下,能够设置指针为空),二是需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么应该使用引用。
6 其它区别
函数参数传递时使用指针或者引用的效果是相同的,都是简洁操作主调函数中的相关变量,当时引用会更加的安全,因为指针一些修改指向,将不能影响主调函数中的相关变量。所以参数传递时尽可能使用引用。这也是引用之所以被引入的厚因。虽然引用只是变量的一个别名,但在函数的参数传递中,变量只能传值,而引用却可以传址且比指针更简洁。
sizeof引用的时候是对象的大小,sizeof指针是指针本身的大小;
指针和引用的自增(++)运算意义不一样;
引用使用时无需解引用(*),指针需要解引用;
在重载操作符并为防止不必要的语义误解时,通常使用引用;
7 代码说明
int a,b,*p,&r=a; //正确
r=3; //正确:等价于a=3
int &rr; //出错:引用必须初始化
p=&a; //正确:p中存储a的地址,即p指向a
*p=4; //正确:p中存的是a的地址,对a所对应的存储空间存入值4
p=&b; //正确:p可以多次赋值,p存储b的地址
通俗化说明
在C和C++中,指针一般指的是某块内存的地址,通过这个地址,我们可以寻址到这块内存;而引用是一个变量的别名,例如我们给小明起了个外号:明明,那我们说明明的时候,就是说小明。
对于指针来说,它是一个地址,这个地址是一个数值,那么就意味这个数值可以为0(空指针),也可以为其他,即指针可以不指向任何东西。
而对于引用来说,他是一个外号,外号一定是“某个存在物体”的外号,所以引用不能为空,即不能存在空引用。
根据以上可知指针和引用的一个重要不同:指针可以为空,引用不能为空。这就意味着我们拿到一个引用的时候,是不需要判断引用是否为空的,而拿到一个指针的时候,我们则需要判断它是否为空。这点经常在判断函数参数是否有效的时候使用。
我们根据前面的描述,还可以知道指针可以多次赋值,即在某时刻可以指向地址1,换个时候可以指向地址2,例如:
int a = 0;
int b = 1;
int *point = NULL;
point = &a; // 在某个时刻,指针可以指向a
point = &b; // 换个时刻,指针可以指向b
而引用则不同,引用只能在初始化的时候就赋好值,之后就不能改变了,用外号的例子来说就是”明明”这个外号在出现的时候就是代指小明,之后“明明”这个外号就绑在小明身上了,它不能过段时间换成小暗的外号。代码如下:
int xiaoming = 1;
int &refence_mingming = xiaoming;
int xiaoan = 2;
refence_mingming = xiaoan; // error,引用不能换了
由以上可以,当我们需要某个是否指向为空的时候,我们就需要使用指针了,还有指向的对象需要变化的时候,我们也需要使用指针。其他地方一般推荐引用。
共同点
都是地址的概念,指针与引用都是让你间接引用其他对象;
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
从对象的角度理解指针
C++primer中对 对象的定义:对象是指一块能存储数据并具有某种类型的内存空间
一个对象a,它有值和地址&a,运行程序时,计算机会为该对象分配存储空间,来存储该对象的值,我们通过该对象的地址,来访问存储空间中的值
指针p也是对象,它同样有地址&p和存储的值p,只不过,p存储的数据类型是数据的地址。如果我们要以p中存储的数据为地址,来访问对象的值,则要在p前加解引用操作符”*”,即*p。
对象有常量(const)和变量之分,既然指针本身是对象,那么指针所存储的地址也有常量和变量之分,常量指针是指,指针这个对象所存储的地址是不可以改变的,而指向常量的指针的意思是,不能通过该指针来改变这个指针所指向的对象。
我们可以把引用理解成变量的别名。定义一个引用的时候,程序把该引用和它的初始值绑定在一起,而不是拷贝它。计算机必须在声明r的同时就要对它初始化,并且,r一经声明,就不可以再和其它对象绑定在一起了。
实际上,你也可以把引用看做是通过一个常量指针来实现的,它只能绑定到初始化它的对象上。
也可以理解引用是操作受限了的指针(仅容许取内容操作)。
引用的主要功能是传递函数的参数和返回值。
C++语言中,函数的参数和返回值的传递方式有三种:值传递、 指针传递和引用传递。
以下是“值传递”的示例程序:
void Func1(int x) {
x = x + 10;
}
int n = 0;
Func1(n);
cout << “n = ” << n << endl; // n = 0
由于Func1 函数体内的x 是外部变量n 的一份拷贝, 改变x 的值不会影响n, 所以n 的值仍然是0。
以下是“指针传递”的示例程序:
void Func2(int *x) {
(* x) = (* x) + 10;
}
int n = 0;
Func2(&n);
cout << “n = ” << n << endl; // n = 10
由于Func2 函数体内的x 是指向外部变量n 的指针,改变该指针的内容将导致n 的值改变,所以n 的值成为10。
以下是“引用传递”的示例程序:
void Func3(int &x) {
x = x + 10;
}
int n = 0;
Func3(n);
cout << “n = ” << n << endl; // n = 10
由于Func3 函数体内的x 是外部变量n 的引用,x 和n 是同一个东西,改变x 等于改变n,所以n 的值成为10。
所以,如果要修改当前被传递的参数的话,要么加一级指针,要么用引用。
对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式象 “值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用” 这东西?
指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。
如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”。
无论你传值还是传指针,函数都会生成一个临时变量,但传引用时,不会生成临时变量,当你传值时,只可以引用值而不可以改变值,但传值引用时,可以改变值,当你传指针时,只可以改变指针所指的内容,不可以改变指针本身,但传指针引用时,既可以改变指针所指的内容,又可以改变指针本身,但传引用主要是它不生成临时变量,不进行返回值copy等,速度快。
-End-
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/16199.html