博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++用参数返回堆上的空间
阅读量:4959 次
发布时间:2019-06-12

本文共 2173 字,大约阅读时间需要 7 分钟。

《高质量c++和c编程》7.4 指针参数是如何传递内存的一节中写道

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"); // 运行错误 }

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

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"<

这个程序可以正确编译执行。而下面代码

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"<

这个代码确实在运行时出错

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

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

在函数结束后保留下来。

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

转载于:https://www.cnblogs.com/wghost/p/3215495.html

你可能感兴趣的文章
6个SQL Server 2005性能优化工具介绍
查看>>
nginx启动、关闭命令、重启nginx报错open() "/var/run/nginx/nginx.pid" failed
查看>>
day14 Python 内置函数、匿名函数和递归函数
查看>>
BZOJ 3097 Hash Killer I
查看>>
UINavigationController的视图层理关系
查看>>
html阴影效果怎么做,css 内阴影怎么做
查看>>
宏观经济
查看>>
综合练习:词频统计
查看>>
BZOJ1026: [SCOI2009]windy数
查看>>
样板操作数
查看>>
64位UBUNTU下安装adobe reader后无法启动
查看>>
iTextSharp带中文转换出来的PDF文档显示乱码
查看>>
qt学习记录-----3.信号与槽的问题
查看>>
『ORACLE』 内置约束(11g)
查看>>
Vue--学习过程中遇到的坑
查看>>
组件:slot插槽
查看>>
.net压缩图片质量(附demo)
查看>>
equals和==的区别
查看>>
Android6.0指纹识别开发
查看>>
java反射机制剖析(二)— Class Loader
查看>>