(1)平常的调用如果传递的是指针参数的话.比如
void a (int * a)
{
*a = 3; //这样则改变了参数的值.
}
因为a代表的是实参中的地址, 改变*a就代表改变实参地址中的值..
但是
void a(int *a)
{
int i = 2;
int* t = &i;
a = t;
}
这样是不会改变的..这样只是改变了指针形参a的指向.注意"形参"两个字..因为当进行函数调用时,都要
进行一次隐含的参数拷贝.其实该参数展开后是这样.
void a(int *a)
{
int* temp = a;
int i = 2;
int *t = &i;
temp = t;
}
看到了吧..改变的只是temp的指向..由于temp和i, *t都是临时变量存储于栈上,在函数结束时,系统自动
回收.所以*a的值是不会改变的. 第一种形式中.展开后依然是.
void a (int * a)
{
int* t = a;
*temp = 3;
}
即使是临时变量..但*temp和*a指向的却是同一个地址,因此该变量值是确定的..就是实参的值..所以能改
变其值.
PS:
指针其实是个神秘的东西,它不像一般变量,简单赋值..指针指向的是变量的内存地址,想想,如果一个指针
指向一块变量的首地址,但是这块首地址由于某种原因,被释放掉了,那该指针就变得没用了,也就是所谓的
野指针了..所以指针是灵活使用的.对其赋值后,要同时关注被赋值的那个变量的值..所以C++推出了const
指针.
const <typename T> *p //该指针是一个常量指针,即一旦指针被赋值后,被赋值的那个必须是常量,而且不能
改变,但是指针却能指向其他变量.
<typename T>* const p//该指针是一个指针常量,即指针只能被赋一次值,但赋值后被指向的变量的值可以改
变.
更复杂一些的例如:
struct m
{
int d;
int c;
};
void a( m* a)
{
a->d = 2;
a->c = 4;
}
展开后其实就是
void a(m* a)
{
m *temp = a;
temp->d = 2;
temp->c = 4; //始终未改变指针的指向..所以*temp和*a其实指向同一块内存区域.因此能操纵同一
变量来达到改变其值的目的.
}
当指针作为数组首地址传递时(平时也可以这么用),指针可以作为数组名来使用
void a(int* p)
{
for( int i = 0; i< 5; i++)
cout << a[i] << endl;
}
void a(int* p)
{
int* temp = p;
for( int i = 0; i< 5; i++)
cout << temp[i] << endl; //同理,未改变指向.
}
(2)
现在再回首看第二种形式,我们再引出来一个新概念,即指向指针的指针.int**p.
void a(int *a)
{
int i = 2;
int* t = &i;
a = t;
}
如果真想改变指针a的值,要怎么做呢.很简单..因为现在是值传递,不要以为指针传递都是传地址,虽然,指
针的值是地址,但是自己也提到了,是指针的"值"啊!!! 所以就是值传递了..呃..
上面的函数展开后其实是这样:
void a(int *a)
{
int *temp = a;
int i = 2;
int *t = &i;
temp = t; //临时变量temp销毁..参数值不变..
}
如果现在改成这样定义.
void a(int** a)
{
int i = 2;
int *t = &i;
*a = t;
}
然后在调用时
int main()
{
int i = 3;
int* p1 = &i;
int** pp = &p1;
a(pp);
cout << *p<< endl;
return 0;
}
没错, 这样就会改变p1的值了..将上面的函数展开.
void a(int** a)
{
int **temp = a; //同时指向同一块内存地址..即指针p1的地址.
int i = 2;
int *t = &i;
*temp = t; //现在*temp表示p1所指向的变量的地址...
} //这样一般是不对的,因为在函数结束时,临时变量i销毁,所以该块内存已经没有...最好就是在参数中传递数组的首地址,然后将数组中的地址做为返回值返回..
但是,上面的函数仅仅是改变了指针p1的指向,但却不能改变变量i的值..因为在函数调用时:
a 中装的指针p1的地址
*a中装的是i的起始地址
**a中装的才是变量i的值..
对*a的修改就是对指针p1的内容的修改...
如果想改变变量i的值,修改**a就行了..