我们经常能遇到这样一种问题,既是声明一个指针,然后想在相关的函数中对其进行分配空间。这样问题如果操作不当,不仅造成内存泄露,而且得不到相应的结果。先看以下例子
void
allocMemory(
char
*
p)
... {
p=(char *)malloc(sizeof(char)*128);
}
int main()
... {
char *s=NULL;
allocMemory(s);//s是否指向堆中分配的内存?
}
... {
p=(char *)malloc(sizeof(char)*128);
}
int main()
... {
char *s=NULL;
allocMemory(s);//s是否指向堆中分配的内存?
}
s是否指向函数内分配的内存呢?回答为不!而且每次调用上面的函数,还会造成内存泄露,因为分配的空间没有释放。要弄清原因,首先要了解参数传递过程中的一些细节。实际上,在函数传递过程中,编译器总是要为函数的每个参数制作一个临时的副本,例如参数p的话,编译器会参生一个_p,是_p=p。如果函数体内修改了_p的内容,哪么p的内容也改变。但是如果修改了_p的地址,p的地址不会变化。;例如下面例子
#include
<
iostream
>
using namespace std;
static int i = 8 ;
void change( int * p)
... {
p=&i;
}
int main()
... {
int j=5;
using namespace std;
static int i = 8 ;
void change( int * p)
... {
p=&i;
}
int main()
... {
int j=5;
int *p=&j;
cout<<"before change,the value of j is:"<<*p<<endl;
change(p);
cout<<"after change,the value of j is:"<<*p<<endl;
}
cout<<"before change,the value of j is:"<<*p<<endl;
change(p);
cout<<"after change,the value of j is:"<<*p<<endl;
}
输出结果是什么呢?是的,两次输出j的值都是5。指针p的地址在调用change()前后没有变化,在change()函数中,只是p的一个副本_p地址发生了改变(指向了i)。由此可见,我们第一例子中s的地址没有发生改变。函数体内分配了内存但是指针s没有指向它。
解决方法:既然我们已经知道了原因,解决方法很简单了。仍以第一个例子为例,我们想要在函数内修改s的地址,我们可以传递一个指针的引用(c++中)或者指向指针的指针。
void
allocMemory(
char
*&
p)
... {
p=new char[128];
}
void allocMemory1( char ** p)
... {
*p=new char[128];
}
int main()
... {
char *s=NULL;
allocMemory(s);
allocMemory1(&s);
}
... {
p=new char[128];
}
void allocMemory1( char ** p)
... {
*p=new char[128];
}
int main()
... {
char *s=NULL;
allocMemory(s);
allocMemory1(&s);
}
传递一个指针的引用利用那个了引用的特征:给引用赋值相当于对于指向的内容进行赋值。对指针的引用进行修改,亦即对指针的地址进行修改。
利用2级指针其本质也是对一级指针的地址进行修改。在函数allocMemory1中,修改了*p的地址亦即修改了s的地址。
另一种方法是函数不带任何参数,在函数内动态申请空间,并返回之。
char
*
allocMemory()
... {
char *p=new char[128];
return p;
}
... {
char *p=new char[128];
return p;
}
需要注意一点的是动态申请的内存在使用之后一定要注意释放。