【c++】指针参数是如何传递内存的

 

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

  1. void GetMemory(char *p, int num)
  2. {
  3. p = (char *)malloc(sizeof(char) * num);
  4. }
  5. void Test(void)
  6. {
  7. char *str = NULL;
  8. GetMemory(str, 100); //str仍未NULL
  9. strcpy(str, "hello"); //运行错误
  10. }

原因是编译器总是为每个参数制作临时副本。指针参数p, 其副本为_p,使_p=p。如果改变了_p所指的内容,相应的p所指的内容也跟着改变(毕竟指向同样的地方)。但是在GetMemory中动态分配内存空间,改变了_p的内容。在调用函数中的p还是指向NULL。再者,因为函数GetMemory中动态分配了空间,但是没释放,这样调用一次函数,就泄露了一次内存。图示:

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

  1. void GetMemory(char **p, int num)
  2. {
  3. *p = (char *)malloc(sizeof(char) * num);
  4. }
  5. void Test(void)
  6. {
  7. char *str = NULL;
  8. GetMemory(&str, 100); //记得加地址符
    strcpy(str, "hello");
    free(str)
  9. }

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

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

  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. }

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

 
 
分类: c++/c

【c++】指针参数是如何传递内存的的更多相关文章

  1. 【转】【c++】指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  2. c++指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  3. 指针参数的传递(节选 C++/C 高质量编程 林锐)

    指针参数是如何传递内存的 如果函数的参数是一个指针,不要指望用该指针去申请动态内存.示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是 ...

  4. 子函数内malloc分配内存,论如何改变指针参数所指内存,二级指针、三级指针的应用

    工作中优化一段代码,代码中有一大段分配堆内存的内容,我觉得这段代码太长了,更适合放在子函数里面. 我把指针作为参数,然后在子函数中malloc分配内存,结果出现了问题,函数结束后,以参数传进来的指针并 ...

  5. 【VS开发】【C/C++开发】C++参数策略传递内存

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  6. PHP函数参数的引用传递和值传递

    函数的参数传递有两种方式 1,值传递 常见的 test($param)  方式就是值传递,在函数内部修改$param,不会影响外部变量$param的值 2,引用传递 参数是引用传递的方式,此时函数内部 ...

  7. 深入理解C指针之二:C内存管理

    原文:深入理解C指针之二:C内存管理 内存管理对所有程序来说都很重要.有时候内存由运行时系统隐式的管理,比如为变量自动分配内存.在这种情况下,变量分配在它所处的函数的栈帧上(每个函数都有它自己的栈帧, ...

  8. 【Qt】信号和槽对值传递参数和引用传递参数的总结

    在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...

  9. C和C指针小记(十六)-动态内存分配

    动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...

随机推荐

  1. 【.NET特供-第三季】ASP.NET MVC系列:MVC与三层图形对照

    近期在开发小组在研究:BS项目中是利用'MVC框架'还是继续沿用'三层'的问题. 由于曾经的.NET项目大多数都是利用三层开发的,所以大多数人都可以对三层进行熟练地运用.而项目的開始我们也曾听说过MV ...

  2. 深入理解C指针之一:初识指针

    原文:深入理解C指针之一:初识指针 简单来说,指针包含的就是内存地址.理解指针关键在于理解C的内存管理模式.C里面有三种内存: ①.静态全局内存(生命周期从程序开始到程序结束,全局变量作用域是全局,静 ...

  3. 从用python做zoj1011发生Non-zero Exit Code错误说起

    近期做了浙大oj的第1011道题,遇见一件奇怪的事.这道题我用c++和php做,提交后都正确.可是用全然同样的逻辑改写成python代码提交后却产生了Non-zero Exit Code的判题结果.p ...

  4. 高速掌握sinox2014激动人心的ZFS和RAID技术

    Sinox2014引入激动人心的zfs系统以及其支持的RAID,让用户高速打造便宜的高可靠性文件server. ZFS文件系统的英文名称为Zettabyte File System,也叫动态文件系统( ...

  5. JVM相关知识(1)

    1.JVM内存管理的机制 内存空间划分为:Sun JDK在实现时遵照JVM规范,将内存空间划分为堆.JVM方法栈.方法区.本地方法栈.PC寄存器. 堆: 堆用于存储对象实例及数组值,可以认为Java中 ...

  6. android 控制手机的体积的大小 切换音效模式

    (1)项目介绍 于android API的AudioManager于,它提供了一种方法来调整电话音量. audioMa.adjustVolume(AudioManager.ADJUST_LOWER, ...

  7. EXCEL导入GridView,然后再汇入数据库.

    原文:EXCEL导入GridView,然后再汇入数据库. 近日项目中有一个多笔料号要输入,我做了一个用javascript复制输入框的功能,可以输入多笔料号. 但是使用者反馈,料号太多,可能几百个料号 ...

  8. C# 对Outlook联系人的增、删、查 

    原文:C# 对Outlook联系人的增.删.查 [转] 注:定义变量 Outlook.Application myOlApp = new Outlook.ApplicationClass(); Out ...

  9. js预解析问题总结

    //示例 1 alert(a) // undefind. alert(fn) // function 整个函数块. var a = 1; function fn(){ return falss; }; ...

  10. Codeforces 10D LCIS 找出最长公共子和产量增加这个序列 dp

    主题链接:点击打开链接 意甲冠军: 特定n长序列 给定k长序列 求LCIS并输出这个子序列 如有多解输出随意解.. = - = 敲的时候听着小曲儿pre的含义还没有想清楚,万万没想到就过了... #i ...