当前位置:编程学习 > C/C++ >>

c++用参数返回堆上的空间

无法返回内存,可以用如下方式


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

void Test2(void)
{
  char *str = NULL;
 GetMemory2(&str, 100); //  注意参数是 &str ,而不是str
 strcpy(str, "hello"); 
  cout<< str << endl;
 free(str); 
}个人的理解就是,实际上指针传递仍然是一种值传递,只不过在参数是指针的时候,传递的是指针的副本,这样你在地址上的操作实际就反映到了内存中,举个例子来说,假设有一个函数

void fun(int  *p)
{
  p = new int;     
}当用调用时fun(q),会产生实参的一个副本设为_p,函数体为副本_p分配了内存,实际上并未改变实参p,这就是GetMemory没有成功的原因。相反,如果我们有如下函数

void fun(int *p)
{
  *p = 3; 
}在这个函数中,当发生实参调用的时候,仍然会产生实参的副本,但是注意这里不是改变副本,而是改变副本指向的内存中的内容,这里p是一个整形指针,在内存中占四个字节,副本和实参指向同一片内存,所以当你

在以副本为地址的内存内赋值3,实际也就是改变了实参指向的内存中的内容。

总结一下就是:指针传递仍然是值传递,所以我们在函数体内只有操作*p才会达到我们的指针传递要求,而不是操作p,这样操作只在副本上,实际并不反映到实参指向的内存。

书中另一种方法是:


char *GetMemory3(int num)
{
  char *p = (char *)malloc(sizeof
 return p;

void Test3(void)
{
  char *str = NULL;
  str = GetMemory3(100); 
 strcpy(str, "hello");
  cout<< str << endl;
 free(str); 
} 实际是将堆的特性和return相结合,堆上分配的内存在函数不会释放,而return实际返回的p的一个副本,但是这里的副本是一个指针,简单的说是一个内存地址,而这个地址在函数结束后并没有释放,所以,我们可以继续

使用。如果是普通的局部变量,return返回它的一个副本,随后局部变量随着函数的结束而被释放,这在某些时候会引起麻烦,比如


char *GetString(void)
{
  char p[] = "hello world";
 return p; // 编译器将提出警告
}
void Test4(void)
{
char *str = NULL;
str = GetString(); // str  的内容是垃圾
cout<< str << endl;
}至于return似乎还有东西说,一时想不起。。。

事情总有例外,今天小妞找我调试程序,发现了一件很奇特的事情,看代码


void getArray(char **s, int N)
{
    std::ifstream in("test.txt");
    if (!in.is_open())
    {
        std::cout<<"error"<<std::endl;
    }
    int i = 0;
    while(i < N)
    {
        s[i] = (char*)malloc(sizeof(char)*100);
        in.getline(s[i], 100);
        ++i;
    }
    in.close();

}
int main()
{
    char **s = (char **)malloc(sizeof(char) * 4);
    getArray(s, 4);
   for (int i=0; i<4; i++)
   {
       std::cout<<s[i]<<std::endl;
   }
    return 0;
}这个程序可以正确编译执行。而下面代码


void getArray1(char **s, int N)
{
//    s = (char **)malloc(sizeof(char) * 4);
    s = new char*[4];
    std::ifstream in("test.txt");
    if (!in.is_open())
    {
        std::cout<<"error"<<std::endl;
    }
    int i = 0;
    while(i < N)
    {
//        s[i] = (char*)malloc(sizeof(char)*100);
        s[i] = new char[100];
        in.getline(s[i], 100);
        ++i;
    }
    in.close();

}

int main()
{
    char **s;
    getArray1(s, 4);
    for (int i=0; i<4; i++)
    {
        std::cout<<s[i]<<std::endl;
    }
    return 0;
}这个代码确实在运行时出错

分析了一下,个人认为虽然两个函数的参数都是char **s,但是一个在main()中先分配,一个直接在getArray中分配,原因就在于此,getarray函数在main函数中先分配了内存,然后传递给它,虽然仍然是值传递,但是

s的元素是指针,getarray函数中在main函数分配的内存上完成了操作,所以当函数结束时,所有操作仍然保留下来。getarray1函数不同,它是在函数体内完整分配内存,然后施加操作的,相当于都在副本上,所有操作都不会

在函数结束后保留下来。

这是个人的一点理解,如有不对的地方还请指教。

 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,