通过下面的小例子,希望帮助大家理解下这两个概念的区别:
如果想改变指针本身而不是它所指向的对象(i),一般有以下两种函数声明的方式:
1 #include <iostream> 2 3 using namespace std; 4 5 void f(int** j) { *j++; } 6 void g(int*& j) { j++; } 7 8 int main() 9 { 10 int i = 0; 11 int* p = &i; 12 13 int size = sizeof(int); 14 cout << "sizeof int:" << size << endl << endl; 15 16 cout << "f(int** j): " << endl; 17 cout << "p " << p << endl; 18 cout << "i " << i <<endl; 19 f(&p); 20 cout << "p " << p << endl; 21 cout << "i " << i <<endl; 22 23 i = 0; 24 p = &i; 25 26 cout << "g(int*& j): " << endl; 27 cout << "p " << p << endl; 28 cout << "i " << i << endl; 29 g(p); 30 cout << "p " << p << endl; 31 cout << "i " << i << endl; 32 33 system("pause"); 34 return 0; 35 }
运行结果如下:
我们看到,调用g(int*& j),p的输出正常,而调用f(int** j)的运行结果却不符合预期,正常情况下p应该为下一个4字节的地址,这是为什么?
问题出在函数定义中,void f(int** j) { *j++; }中++的运算优先级高于*,所以并没有出现预期的结果,将定义改为:void f(int** j) { (*j)++; }
再次运行代码:
这次结果符合了预期。
分析:当函数的形参为指针时,在函数内部会复制实参指针,因而形参(ip)在函数内部的任何改变都无法影响实参。然而,传入的指针形参却可以改变指针指向的对象(*ip)的值。
1 void reset(int* ip) 2 { 3 ip = 0; //形参在函数内部的改变无法影响实参 4 *ip = 0; //改变了ip所指向对象的值 5 }
当函数的形参为指向指针的指针,如本例void f(int** j) { (*j)++; }中,是如何改变j指向的对象呢?其中j,*j,i之间的指向关系如下
参数j是一个指向指针的指针,说白了就是*j的地址,j指向的对象就是*j(对象i的地址)。将j传入函数内部,产生j的拷贝j',改变j‘指向的对象的值,就改变了*j,从而达到目的,看到指针本身*j的内容增加了,而不是它指向的对象(i)增加了。
2,
之前没有碰到过这类情况,也不知道实际工程中有什么奥妙,先来一个小的测试例子看一下运行结果:
int a = 1;
int b = 2;
int *tmp = &a;
int *p = tmp;// 第二种情况:int *&p = tmp;(此既是指向指针的引用)
p = &b;
*p = 5;
1、测试此时的a, b , *tmp, *p分别是什么: a = 1, b = 5, *tmp = 1, *p = 5;
2、如果是上述第二种情况,即指向指针的引用,那么这些变量又该是什么值呢?答案是:
a = 1, b = 5, *tmp = 5, *p = 5;
这是因为指向指针的引用,不仅改变了指针所指的对象,也改变了指针本身。