传递动态内存

来源:互联网 发布:linux系统关闭进程 编辑:程序博客网 时间:2024/05/11 05:42

这是一块比较头疼的知识点,但又是面试公司最喜欢出的一类面试题,所以,既便再怎么不愿意面对,我们也要来搞定它。


在这之前,为大家收集了下内存操作及问题相关知识点,以便更好的深入探讨动态内存的传递。

【内存操作及问题相关知识点】

(1)内存分配方式有三种:

●从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
●在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
●从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活。

(2)指针的操作流程

     申请并初始化或设置为空:int *pInt=NULL;
     开辟空间或者使其指向对象:pInt=new Int(3);或者int i=3;pint=&i;
        用指针(更确切地说是操作内存,在使用之前加if(pint!=NULL)或者assert(pInt!=NULL)后再使用,以防内存申请失败的情况下使用指针):
if(p!=NULL) {use pint};
       释放使用完的内存.free(pInt);
       置指针为空pInt=NULL;(避免野指针的出现)

(3) 在函数的参数传送中,编译器总是要为函数的每个参数制作临时副本,假如参数为p的话,那么编译器会产生p的副本_p,使_p=p; 假如函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因.


了解了这些,我们再来看一个例子:

void GetMemory( char *p ,int num)
{
p = ( char * ) malloc (sizeof(char) *num );
}
int main()
{
char *str = NULL;
GetMemory(str,100);
strcpy(str,"hello");
return 0;
}


这是一种最常见的错误,GetMemory函数中的*p实际为str的一个副本,虽然我们成功的申请了一块内存,但它仅仅停留在“申请一块内存”阶段,只改变了p的内存地址,并没有返回改变的p,因此str不指向p所申请的内存,str一直逗是“NULL”,而且p指针所申请的地址得不到释放,最后会导致内存泄漏。

不过,也不用怕,我们有至少三种解决方案来避免此类问题。

【问题解决方案】

方法一.使用引用,因为它会使你少犯一些错误.以下是一个例子.

void GetMemory( char * &p ,int num) //注意变量* &p
{
p = ( char * ) malloc (sizeof(char) *num );

memset( p,0x00,num );   //先赋值再使用
if(num >= 13)
strcpy(p ,"Hello World!" );
}

void main()
{
char *p1 = NULL;
GetMemory(p1,15);

        if(p1 != NULL)
{
   char *pTemp = p1;
   while( *pTemp != '\0')
     cout << *pTemp++;
   pTemp = NULL;
   strcpy(p1,"AAAAAAAA");
   free(p1);
   p1=NULL;
}
}


方法二.利用二级指针

void GetMemory (char **p,int num)
{
*p = (char *)malloc ( sizeof(char) *num );
}

int main()
{
char *str =NULL;
GetMemory (&str,100); //参数为 &str
strcpy (str,"hello");

cout << *str <<endl;
cout << str <<endl;
cout << &str <<endl;

return 0;

}


大家有兴趣还可以算下,一下三个cout输出的值是什么
cout << *str <<endl;
cout << str <<endl;
cout << &str <<endl;

方法三. 用函数返回值来传送动态内存

char * GetMemory (char *p,int num)
{
p = (char *)malloc ( sizeof(char) *num );
return p;
}


int main()
{
char *str =NULL;
str = GetMemory (str,100);

strcpy(str,"hello");

cout<<str<<endl;
return 0;
}


值得注意的是,如果你的函数采用这样的写法:
char * GetMemory (void)
{
char *p = "Hello World"
return p;
}
你是不能返回什么动态内存的,因为p永远指向的"hello word"(常量字符串).内存在位于静态存储区
上分配,你无法改变.(你想要得到动态内存我们一定要看到malloc或者new).


将此题推广到整型变量传值,我们可以看如下例子:
void GetMemory(int *x)
{
*x =5;
}
int main()
{
int v;
GetMemory(&v);
cout <<v<<endl;
return 0;
}

//*x是地址里的值,V为副本,直接修改地址,不需要返回值也可以把V修改,因为V所指向的地址改变了。


另外要提一下的,释放指针的时候要注意不要delete两次,delete时候不需要检查NULL


 

转载网址:http://hi.baidu.com/pearry/blog/item/406cfc9737a9ef45d0135e3e.html

原创粉丝点击