指针和引用,傻傻分不清楚?

999 阅读3分钟

总的来说,有三个最基本的区别:

  1. pointer可以指向NULL,但reference不可以为NULL;
  2. 因此,reference在初始化时必须赋值,但pointer可以在任何时候被赋值;
  3. reference一旦被赋值就不可更改,但pointer仍可以更改其指向

举个例子:

int a = 1;
int b = 2;
int* p;		// OK
int& q;		// compile error

int& q = b;	// q = 2
&q = a;		// complie error

更详细的在这个问题里有很好的解答:

stackoverflow.com/questions/5…

主要列了9点:

1. pointer可以更改指向:

int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;		// 指针p指向&y,也就是类型为int的变量y的地址,此时*p = 6
*p = 10;	// *p为指针p指向地址中存储的值,即y的值,修改该值为10,故y的值被修改为10

reference一旦被赋值就不可更改,并且在初始化时必须赋值:

int x = 5;
int y = 6;
int &q;		// error
int &r = x;

2. pointer variable是有自己独立内存地址的

这个地址可以通过&取址取到,并且可以通过 sizeof 取到该内存的大小;

但reference本身的地址和大小是不可见的,这也就是很多人说的可以把reference理解为别名,对reference使用&或sizeof返回的是与该reference关联的变量的 &sizeof

int x = 0;
int &r = x;		// r就是x的别名,通过r也可以拿到x的值,r和x在实际内存中关联的是同一个地方
int *p = &x;	// 指针p指向的是x所在的地址,而指针变量p本身存储在内存中其他地址,其值就是x的地址
int *p2 = &r;	// 指针p2指向的是r关联的地址,也就是x

assert(p == p2);	// &x == &r,p和p2指向的是同一地址 
assert(&p != &p2);	// 但p和p2本身在内存中的位置并不相同

3. 可以创建指向指针的指针,但不可以创建指向引用的指针

int **p;	// OK
int &*pr;	// ill-formed

为什么不可以创建指向引用的指针呢?

stackoverflow.com/questions/1…

也可以参照C++ Primer中的说法:

Because references are not objects, they don't have addresses. Hence, we may not define a pointer to a reference.

4. 可以创建指针数组,但不能创建引用数组

int *ap[];	// ok, array of pointers
int &ar[];	// ill-formed, array of references

这个回答说的也很清楚:

stackoverflow.com/questions/5…

因为在数组中索引本身就是用指针的方式实现的,数组中也支持指针运算(pointer arithmetic, int a[2] = {20, 30}, 那么 a+1 其实就是 a[1] ,即 30 )。

若支持引用数组,那就需要支持指向引用的指针,并对指针运算进行定义。第3点已经解释过,指向引用的指针是不被允许的。

5. 指向指针的指针可以嵌套很多层,但引用只能有一层,即没有引用的引用。

int x = 0;
int y = 0;
int *p = &x;
int *q = &y;
int **pp = &p;	// 指针pp指向指针p,而指针p指向x,因此pp间接指向x
**pp = 2;	// 其实修改的是x的值
pp = &q;	// pp又指向了q
**pp = 4;
assert(y == 4);
assert(x == 2);

6. 指针可以为空,但引用不可以为空

7. 数组中指针可以进行指针运算,第4点里解释过

8. 指针需要通过 * 符号进行解引用

拿到的才是该指针指向的东西,但引用作为别名,本身就是他关联的东西;

还有就是,指向 class/struct 的指针用 -> 访问成员,引用用 .

9. const引用和右值引用可以关联到临时变量上,但指针不行

const int &x = int(12);		// legal C++
int *y = &int(12);			// illegal to take the address of a temporary