传递双重指针申请内存,典型用法

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

如果函数的参数是一个指针,不要指望用该指针去申请动态内存。如下示例中,Test函数的语句GetMemory(str, 100)并没有使str获得期望的内存,str依旧是NULL,为什么?

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

}

毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。

如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例:

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);

}

由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例:

char *GetMemory3(int num)

{

 char *p = (char *)malloc(sizeof(char) * num);

 return p;

}

void Test3(void)

{

 char *str = NULL;

 str = GetMemory3(100);

 strcpy(str, "hello");

 cout<< str << endl;

 free(str);

}

用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例:

char *GetString(void)

{

 char p[] = "hello world";

 return p; // 编译器将提出警告

}

void Test4(void)

{

 char *str = NULL;

 str = GetString(); // str 的内容是垃圾

 cout<< str << endl;

}

用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello world”而是垃圾。

如果把上述示例改写成如下示例,会怎么样?

char *GetString2(void)

{

 char *p = "hello world";

 return p;

}

void Test5(void)

{

 char *str = NULL;

 str = GetString2();

 cout<< str << endl;

}

函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。

【VS开发】【C/C++开发】传递双重指针申请内存,典型用法的更多相关文章

  1. Delphi 的内存操作函数(1): 给字符指针分配内存

    马上能想到的函数有: GetMem AllocMem ReallocMem FreeMem GetMemory ReallocMemory FreeMemory New Dispose NewStr ...

  2. Delphi 的内存操作函数(1): 给字符指针分配内存( 给字符指针(PChar、PWideChar、PAnsiChar)分配内存最佳的选择是StrAlloc。分配内存的时候会对字符串进行初始化)

    马上能想到的函数有: GetMem AllocMem ReallocMem FreeMem GetMemory ReallocMemory FreeMemory New Dispose NewStr ...

  3. 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明

    [VS开发][编程开发][C/C++开发]结构体中的数组与指针的内存分配情况说明 标签:[VS开发] [编程开发] 主要是疑惑在结构体定义的数组的内存空间与指针动态分配的内存空间,在地址上连续性.以及 ...

  4. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  5. iOS开发系列--并行开发其实很容易

    --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的, ...

  6. iOS开发系列--网络开发

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  7. C++ 二维数组(双重指针作为函数参数)

    本文的学习内容参考:http://blog.csdn.net/yunyun1886358/article/details/5659851 http://blog.csdn.net/xudongdong ...

  8. Loadrunner 脚本开发-利用loadrunner开发Windows Sockets协议脚本

    脚本开发-利用loadrunner开发Windows Sockets协议脚本 by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 实践举例 Socket服务端简单实 ...

  9. [转] C++的引用传递、指针传递参数在java中的相应处理方法

    原文出处:[http://blog.csdn.net/conowen/article/details/7420533] 首先要明白一点,java是没有指针这个概念的. 但是要实现C++的引用传递.指针 ...

随机推荐

  1. MySQL主从同步、读写分离配置步骤、问题解决笔记

    MySQL主从同步.读写分离配置步骤.问题解决笔记 根据要求配置MySQL主从备份.读写分离,结合网上的文档,对搭建的步骤和出现的问题以及解决的过程做了如下笔记:       现在使用的两台服务器已经 ...

  2. [转]Normal Map中的值, Tangent Space, 求算 Tangent 与 Binormal 与 TBN Matrix

    原文出处 https://www.cnblogs.com/lookof/p/3509970.html - Normal Map中的值 -   有没有想过,Normal Map(法线贴图)为什么看上去都 ...

  3. 请求出现Referrer Policy: no-referrer-when-downgrade

    请求出现Referrer Policy: no-referrer-when-downgrade,一直请求不成功,原因是请求连接出现问题,我这里的问题是api前少了/,导致字段和域名拼接起来,所以请求U ...

  4. MFC GDI绘图

    DC——MFC设备描述表类(也叫设备环境.设备上下文).默认起始点(0,0),带To的函数会移动起始点到指定位置. 新建单个文档的MFC应用程序,类视图——View项的属性——消息,WM_PAINT, ...

  5. window上git bash运行错误记录

    错误现象:每次启动git bash报出如下错误gitbash  0 [main] bash 11928 fork: child -1 - CreateProcessW failed for 'D:\P ...

  6. python-解决pip安装速度慢的问题--豆瓣镜像

    https://www.cnblogs.com/ZhangRuoXu/p/6370107.html https://blog.csdn.net/tianguiyuyu/article/details/ ...

  7. dup2函数

    将当前系统中的进程信息打印到文件中 命令行:ps aux > out 将ps得到的信息重定向到out文件中 使用dup2文件在程序中完成. int dup2(int oldfd,int newf ...

  8. codeforces#1157D. Ehab and the Expected XOR Problem(构造)

    题目链接: http://codeforces.com/contest/1174/problem/D 题意: 构造一个序列,满足以下条件 他的所有子段的异或值不等于$x$ $1 \le a_i< ...

  9. python能用来做什么?这3大主要用途你一定要知道!(实用)

    导读:如果你想学Python,或者你刚开始学习Python,那么你可能会问:“我能用Python做什么?” 这个问题不好回答,因为Python有很多用途. 但是随着时间,我发现有Python主要有以下 ...

  10. 教你快速写一个EventBus框架

    前言EventBus相信大多数人都用过,其具有方便灵活.解耦性强.体积小.简单易用等优点,虽然现在也有很多优秀的替代方案如RxBus.LiveDataBus等,但不可否认EventBus开创了消息总线 ...