参数策略

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

  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, ); //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, ); //记得加地址符
  9. strcpy(str, "hello");
  10. free(str)
  11. }

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

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

  1. #include <iostream>
  2. #include <string>
  3. #include <cstring>
  4. #include <cstdlib>
  5. using namespace std;
  6. void GetMemory(char *&p, int num)
  7. {
  8. p = (char *)malloc(sizeof(char) * num);
  9. }
  10.  
  11. void Test(void)
  12. {
  13. char *str = NULL;
  14. GetMemory(str, );
  15. strcpy(str, "hello");
  16. cout << str << endl;
  17. free(str);
  18. }
  19. int main()
  20. {
  21. Test();
  22. }

这里注意指针的引用 为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(); //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. }

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

原文路径:http://www.cnblogs.com/kaituorensheng/p/3246900.html

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

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

    [c++]指针参数是如何传递内存的   如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *) ...

  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. Maven实战(九)---模块聚合和继承

    类之间有聚合和继承关系,Maven也具备这种设计原则. 那么Maven的pom是怎样进行聚合与继承的呢? 一.什么是聚合?为什么要用聚合? 上一篇博客介绍了模块化的基本知识. 有了模块化,那么我们项目 ...

  2. Spring boot设置启动监听端口

    一.通过配置 修改application.properties 在属性文件中添加server.port=8000 二.直接看代码: @Controller @EnableAutoConfigurati ...

  3. Math.Celing、Math.Floor、Math.DivRem与Math.BigMul

    返回大于或等于指定数字的最小整数.例如: double a=Math.Celing(0.00);  //0 double a=Math.Celing(0.40);  //1 double a=Math ...

  4. 啸叫抑制(howling suppression)

    作者:桂. 时间:2017-05-16 链接:http://www.cnblogs.com/xingshansi/p/6862683.html 前言 下午看到群里讨论有人提到这个问题,记录一下. 一. ...

  5. 关于Xilinx MicroBlaze应用modelsim se仿真问题(EDK:3593 - Unable to locate the precompiled library microblaze_v8_50_c)

    ERROR:EDK:3593 - Unable to locate the precompiled library microblaze_v8_50_c. The file D:\Xilinx\14. ...

  6. [k8s] kubelet单组件启动静态pod

    kubelet单组件启动静态pod 无需k8s其他组件,单独下载kubelet的二进制,可以启动静态pod. 静态pod不受api管理,kubectl get po可以看到,但是kubectl del ...

  7. rabbitmq 常用的一些命令

    rabbitmqctl set_user_tags admin administrator #给用户设置角色 rabbitmqctl set_permissions -p emove admin &q ...

  8. JAVA calling convention

    http://stackoverflow.com/questions/28126082/where-does-the-jit-compiled-code-reside https://wiki.ope ...

  9. Python中赋值、浅拷贝与深拷贝

    python中关于对象复制有三种类型的使用方式,赋值.浅拷贝与深拷贝.他们既有区别又有联系,刚好最近碰到这一类的问题,研究下. 一.赋值 在python中,对象的赋值就是简单的对象引用,这点和C++不 ...

  10. 0058 Spring MVC如何向视图传值--Model--ModelMap--ModelAndView--@ModelAttribute

    MVC,模型.视图.控制器,请求来了,控制器负责找到Controller进行一通计算,计算的结果放到模型里,再找视图把结果呈现出来. 请求里一般都包含了一些参数,前面说了,Spring MVC有很多种 ...