楼主刚从java转到c++,被这个指针搞得头疼,今天晚上碰到这个问题,想了好久,翻书也翻了很久,终于弄明白这其中的奥秘。
首先我们得明白c++中的函数参数传递一个重要规则X(姑且命名X,方便下面叙述)是:
每次调用一个函数,都会重新建立一个形参(类似于临时变量),传入的实参作为初始化值拷贝给形参,一旦实参的值拷贝给形参后,形参和实参其实是两个不同的对象了(c++Prime原话,啃书!!!),就互不干涉了。这句话真的太重要!!!
接下来,通过一个简单的例子,来演示一下指针作为函数形参的两个容易混淆的问题。
1)可以改变指针指向的内容:
void test(int* s) {//指针作为形参
//s = new int(2);//p指向2这块内存空间
*s = 20;//指针指向的内容修改
}
int main() {
int a = 1000;
int* p = &a;
cout << "调用前p的地址" << p << endl;//调用前p的地址004FFEC0
cout << "调用前p指向的值" << *p << endl;//调用前p指向的值1000
test(p);
cout << "调用后p的地址" << p << endl;//调用后p的地址004FFEC0
cout << "调用后p指向的值" << *p << endl;//调用后p指向的值20
}
如上面代码所示,main函数中的指针p原本是指向a的内存,且存的数是1000,输出为:
“调用前p的地址004FFEC0”
“调用前p指向的值1000”
根据X规则,test()函数在调用时,形参s生成临时变量int* s,实参p用于s的初始化,所以s等于p,也可以理解s和p指向同一块内存,故通过*s对指针指向的内容进行修改:*s= 20,也就是等同于*p=20!所以调用后输出:
“调用前p的地址004FFEC0”
“调用前p指向的值20”
即地址没变,但是值修改了。
由这个例子其实可以看出来,地址没改变,改变了指针指向的内容
2) 不可以改变指针的地址:
void test(int* s) {//指针作为形参
s = new int(2);//p指向2这块内存空间
cout << "调用后s的地址" << s << endl;//调用后s的地址01034FC8
//*s = 20;//指针指向的内容修改
}
int main() {
int a = 1000;
int* p = &a;
cout << "调用前p的地址" << p << endl;//调用前p的地址010FF7BC
cout << "调用前p指向的值" << *p << endl;//调用前p指向的值1000
test(p);
cout << "调用后p的地址" << p << endl;//调用后p的地址010FF7BC
cout << "调用后p指向的值" << *p << endl;//调用后p指向的值1000
}
这个例子中我让test函数对指针的指向进行改变。main中的p仍然指向a,在调用后,根据输出语句的地址发现:指向的还是a,地址未发生改变。但是s的地址和p的地址不一样了,因为“一旦实参的值拷贝给形参后,形参和实参其实是两个不同的对象了,就互不干涉了。”注意!这个s和p不是一个东西了。
3)针对1)和2)的思考
为什么指针作为形参可以改变指针指向的内容,却不可以改变指针的指向?我觉得一定得从函数的参数传递本质着手,函数参数传递的规则是实参是形参的初始化,一旦实参的值拷贝给形参后,形参和实参其实是两个不同的对象了。这个一定好好理解一下!基于这个规则:
当一个函数将指针作为形参时,我们给这个形参传入一个实参(指针(非引用类型)),这个实参的值究竟是什么?其实是指针的地址值,这个地址值传给形参后,后续形参怎么折腾,跟这个实参无关的。如:1)中只是*s = 20,这个s其实就是p,因为s没有对指针指向进行修改(可以理解成s和p指向同一个内存,那么s修改了指针指向的内存保存的值,p指向的值当然也得变)。2)中 s = new int(2);就是把s指向了另一个内存,虽然test函数中s的地址变了;但是跟p没有半毛钱关系,所以main中输出的两个p的地址还是一样的。归根结底还是因为“一旦实参的值拷贝给形参后,形参和实参其实是两个不同的对象了,就互不干涉了”。 这句话理解了, 就啥都明白了。
形象一点的说就是:
我把我家的钥匙(实参)拷贝了一份给你(形参),你可以用拷贝的钥匙开我家的门,拿我家的东西,完全没问题,但是你非要去开锁店把我家的钥匙改造成另一个样子,即使可能你可以用这个改造的钥匙去开别人家的门(改变指向),但是你根本不会影响我自己手上这把钥匙继续开我家的门(不改变实参的指向)。
第一次写帖子,只是想分享今天学到的心得。可能总结的不好,不喜勿喷。如果有错的地方,希望大佬们给与指正!感谢!