关于一道看了很多次,但每次都被似懂非懂的问题

#include <iostream> 
void foo(char *p)
{
   p = "after foo()";
}     
void main()
{
   char *p = "before foo()";
   foo(p);     
   cout <<p <<endl;   
}

看到这个,大家很熟悉吧,估计c++面试题中会出现不少。最后输出是before foo(),为什么foo函数没有把p的内容改变。为什么明明传入了指针但改不了指针指向地址的值呢?

有一点东西必须说明一下的就是,"before foo()"这个字符串其实代表了一个地址。地址的内容是before foo()这几个字符串。同理"after foo()"也是一个地址。

当实参p传入foo时,形参p和实参p其实都是指向"before foo()"的地址,但是后来foo里面把形参p指向的地址变为了"after foo()"的地址,就再不关"before foo()"这块内存什么事了,所以其实形参p改变的只是自己指向的地址。不要以为p = "after foo()"是把p指向的地址内的字符串替换为了"after foo()"

类似的函数如:

void foo(char *p)
{
   p = new char[10];
}

调用这个函数也不会给实参分配内存,它只是将形参指向一块新分配的内存。

如果foo是这样的:

void foo(char *p)
{
   *p = '1';
}

这时候实参p指向的地址的值就真的是实实在在地被修改了。但是实参是指向"before foo()"的话,这时传入foo,会发生写入报错,因为"before foo()"所在的内存受到了写保护。

如果实参是类似char* p = new char[10]{'f','f','\0'};这样声明的,传入foo,就不会有什么问题,实参p指向地址的首个字符就会从'f'变为'1'

 

如果想将实参p = "before foo()"变为"after foo()",可以将foo改为

void foo(char **p)
{
*p = "after foo()";
}

调用的时候传入p指针的地址就可以了。

foo(&p);

这时候是将实参p指向的地址改变了,而不是改变p指向地址的内容。

 

当然方法很多,就不多说了。这些知识可能很多人都知道,不过如何表达让其他人明白就因人而异了,或者有人觉得我写得容易理解,那就看看吧。大神路过跪求指导,或者直接无视继续前进

 

posted @ 2016-03-25 17:04  Haha哈哈哈  阅读(385)  评论(0编辑  收藏  举报