指针参数是如何传递内存的

参数策略

如果函数的参数是一个指针,不要指望用该指针去动态申请内存。如下:

 

void GetMemory(char *p, int num)
{
    p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
    char *str = NULL;
    GetMemory(str, 100);     //str仍未NULL
    strcpy(str, "hello");    //运行错误
}

 

原因是编译器总是为每个参数制作临时副本。指针参数p, 其副本为_p,使_p=p。如果改变了_p所指的内容,相应的p所指的内容也跟着改变(毕竟指向同样的地方)。但是在GetMemory中动态分配内存空 间,改变了_p的内容。在调用函数中的p还是指向NULL。因为,实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量作为函数参数也要遵循这一规则。不可能通过调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。 再者,因为函数GetMemory中动态分配了空间,但是没释放,这样调用一次函数,就泄露了 一次内存。图示:

如果非得用指针参数申请内存,可以用指针的指针作为参数申请内存

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
    char *str = NULL;
    GetMemory(&str, 100);  //加地址符,用&str作为函数参数,是为通过传递str的地址给形参来实现实参值的改变,*p就是str地址值
    strcpy(str, "hello");    
    free(str)
 }

 

原理是一样的,比较难理解,图示表示:

比较好的方法是传指针的引用

 

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
void GetMemory(char *&p, int num)
{
    p = (char *)malloc(sizeof(char) * num);
}

void Test(void)
{
    char *str = NULL;
    GetMemory(str, 100);
    strcpy(str, "hello");
    cout << str << endl;
    free(str);
}
int main()
{
    Test();
}

 

这里注意指针的引用 为char* &a,要是不好理解可以这样:

 

1     typedef char* pchar;
2     pchar &a

 

返回值策略

可以用函数返回值来传递动态内存。这中方法比“指针的指针”简单多了

 1 char *GetMemory(int num)
 2 {
 3      char *p = (char *)malloc(sizeof(char) * num);
 4      return p;
 5 }
 6 void Test(void)
 7 {
 8     char *str = NULL;
 9     str = GetMemory(100);  //str指向了动态分配的空间
10     strcpy(str, "hello"); 
11     free(str)
12  }

 

在使用返回值时,千万别返回指向“栈内存”的指针、引用,因为该内存在函数结束时自动消亡了,返回的指针是个野指针了。例如

 

 1 char *GetString()
 2 {
 3      char p[] = "hello world"; //数组内容存储在栈区,函数结束时,会释放掉
 4      return p;
 5 }
 6 void Test(void)
 7 {
 8     char *str = NULL;
 9     str = GetString();      //因为非配的内存早已释放掉,此时的str是个野指针,内容是垃圾
10    cout << str << endl;
11  }

在函数中不定义数组,定义指针,示例:

 1 char *GetString()
 2 {
 3      char *p = "hello world"; //数组内容存储在静态区,函数结束时,不会释放掉
 4      return p;
 5 }
 6 void Test(void)
 7 {
 8     char *str = NULL;
 9     str = GetString();      
10     cout << str << endl;
11  }

此时的程序是正确的,但是有一点,此时分配的内存处于静态区,是只可以读取但是不可以修改的。

 

 

 

posted on 2014-04-11 08:42  民天  阅读(231)  评论(0)    收藏  举报

导航