关于一道看了很多次,但每次都被似懂非懂的问题
#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指向地址的内容。
当然方法很多,就不多说了。这些知识可能很多人都知道,不过如何表达让其他人明白就因人而异了,或者有人觉得我写得容易理解,那就看看吧。大神路过跪求指导,或者直接无视继续前进