总的来说,有三个最基本的区别:
- pointer可以指向NULL,但reference不可以为NULL;
- 因此,reference在初始化时必须赋值,但pointer可以在任何时候被赋值;
- 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