![344184b8d420eb2c7858192c589d85aa.png](https://i-blog.csdnimg.cn/blog_migrate/6c0aad0b36366e46827e3b8b5de3ac1c.jpeg)
从表面上看,引用和指针非常相似,都用于使一个变量提供对另一变量的访问。 由于两者都提供了许多相同的功能,因此通常不清楚这些不同机制之间的区别。 在本文中,我将尝试说明指针和引用之间的区别。
指针:指针是保存另一个变量的内存地址的变量。要访问指针指向的内存位置,需要使用*运算符取消对指针的引用。
引用:引用变量是别名,也就是已经存在的变量的另一个名称。引用和指针一样,也是通过存储对象的地址来实现的。
引用可以看作是一个常量指针(不要与指向常量值的指针混淆!)使用自动间接寻址,即编译器将为您应用*运算符。
int i = 3; // A pointer to variable i (or stores// address of i)int *ptr = &i; // A reference (or alias) for i.int &ref = i;
区别:
1. 初始化:指针可以通过以下方式初始化:
int a = 10; int *p = &a; OR int *p; p = &a;
引用:
int a=10;int &p=a; //it is correct butint &p; p=a; // it is incorrect as we should declare and initialize references at single step.
注意:编译器之间的差异可能有所不同。
2. 重新分配:可以重新分配指针。该属性对于实现诸如链表,树等数据结构非常有用。请参见以下示例:
int a = 5;int b = 6;int *p;p = &a;p = &b;
另一方面,引用不能重新分配,必须在初始化时分配。
int a = 5;int b = 6;int &p = a;int &p = b; //At this line it will show error as "multiple declaration is not allowed".However it is valid statement,int &q=p;
3. 内存地址:指针在堆栈上具有其自己的内存地址和大小,而引用共享相同的内存地址(与原始变量),但也占用堆栈上的一些空间。
但是,如果我们需要引用的真实地址,则可以通过编写以下语句在turbo IDE中找到它:
int &p = a; cout << &(&p);
4. NULL值:指针可以直接分配为NULL,而引用则不能。 与引用关联的约束(无NULL,无重新分配)确保基础操作不会遇到异常情况。
5. 间接寻址:可以有指向指针的指针提供额外的间接寻址级别。
In Pointers,int a = 10;int *p;int **q; //it is valid.p = &a;q = &p;Whereas in references,int &p = a;int &&q = p; //it is reference to reference, so it is an error.
6. 算术运算:可以对指针执行各种算术运算,而没有称为引用运算的东西(但是您可以获取引用指向的对象的地址,并像&obj + 5中那样对它进行指针运算)。
什么时候使用指针与引用
两者性能完全相同,因为引用在内部作为指针实现。但是,您仍然可以记住一些要点,以决定何时使用什么:
1.使用引用
在函数参数和返回类型中。
2.使用指针
1)如果需要使用指针运算或传递NULL指针,请使用指针。例如对于数组(请注意,数组访问是使用指针运算实现的)。
2)因为要指向不同的单元格,所以要实现诸如链表,树等的数据结构及其算法,我们必须使用指针的概念。
示例,
指针
int arr[] = {10,20,30};int *p,i ;p = arr;for(i = 0; i<3 ; i++){cout << *p << endl;p++;}
输出:
102030
注意:这里的指针将在基址之前
现在在引用中使用相同的代码
int arr[] = {10,20,30};int &p = arr[0];int i;for(i = 0; i<3 ; i++){cout << p << endl;p++; //here it will increment arr[0]++}
输出:
101112
注意:这里的指针将仅位于基地址。
尽可能使用引用,必要时使用指针。当您不需要重新指向时,通常首选引用而不是指针。
上面提到的例外情况是,函数的参数或返回值需要一个“sentinel”引用(一个不引用对象的引用)。这通常最好通过返回/获取指针,并赋予空指针这种特殊的意义(引用必须始终别名对象,而不是取消引用的空指针)来完成。