看 高质量C++编程指南 碰到的指针的问题

thisisll 2005-11-24 03:31:29
7.4指针参数是如何传递内存的?
如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使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"); // 运行错误}
示例7-4-1 试图用指针参数申请动态内存

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

-------------------------
他解释说有个副本,为什么要造个副本?
下下一个例子7-4-3
他为什么一return P的值就成副本了
还有为什么指针的指针就没有副本的问题?
总之是我没看明白,希望大家给解释下
-------------------------

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

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); }
示例7-4-2用指向指针的指针申请动态内存

由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例7-4-3。
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); }
...全文
199 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
luvybird 2005-11-30
  • 打赏
  • 举报
回复
up
寻开心 2005-11-24
  • 打赏
  • 举报
回复
"进入函数体的是指针指向的地址(假设是0x0001),而不是指针那4个字节自身的地址(假设是0xA000) 所以他会在0x0001那里写上malloc申请出来的地址
"
基本正确

1 变量的数值 和 变量的地址 是两个概念, 这点可以理解吧
2 指针变量的数值 和 指针变量的地址 当然也就不同了
3 指针的数值是0x0001,也就是指针指向的地址
指针的地址是另外的别的(就是你所谓的4字节的地址0xa000)
4 传递到函数体里面的是指针的数值,也就是 0x0001; 而不是指针的地址0xa000
5 因此在函数体里面只知道0x0001这个地方,可以对其修改
不知道0xa000,所以指针变量自己不会变化
thisisll 2005-11-24
  • 打赏
  • 举报
回复
我声明一个指针
一出来不是NULL
是个垃圾值
我只是假设一下
dragonzxh 2005-11-24
  • 打赏
  • 举报
回复
就是你传指针的指针就是传指针的地址,传进去的指针P的地址和副本指针_P的地址不一样,但是P和副本_P本身的指向的地址是一样的。。。。
bing_huo 2005-11-24
  • 打赏
  • 举报
回复
假设:
外部指针p值的地址是0xA000 因为还没有分配内存 所以指向无效地址空间 假设为0x0001

通过传值方式 传递到函数内部 系统构造一个临时对象 tp (系统构造的是无名字的临时对象,为了方便叙述 假设名字为tp)

tp拥有和p同样的指向 0x0001 和不同的值地址空间假设为0xA0002

内部分配内存后 tp 指向已分配的内存 假设为 0x00FF 然后函数返回 注意 这中间p 还是p 没有任何改变。。。所以自然申请不到内存

函数返回时tp被销毁 tp指向的内存被泄露(因为除了tp外 再也没有其他方法访问和释放0x00FF起始的这块内存)
moany 2005-11-24
  • 打赏
  • 举报
回复
你对指针还不怎么理解,指针在初始化之前,是指向NULL的,没有假设0x0001之类的
lzp229 2005-11-24
  • 打赏
  • 举报
回复
用传进去指针的指针来改变指针,跟传指针进去来改变指针所指内容一个道理。
thisisll 2005-11-24
  • 打赏
  • 举报
回复
void GetMemory2(char **p, int num)
{*p = (char *)malloc(sizeof(char) * num);}

void Test2(void){
char *str = NULL;
GetMemory2(&str, 100);<<---所以这里用的是引用进入函数体的就是这个指针的本身
cout<< str << endl;free(str);
}
thisisll 2005-11-24
  • 打赏
  • 举报
回复
看了这么多后
我的理解是这样的:
进入函数体的是指针指向的地址(假设是0x0001),而不是指针那4个字节自身的地址(假设是0xA000)
所以他会在0x0001那里写上malloc申请出来的地址

我想应该是这样的吧
bing_huo 2005-11-24
  • 打赏
  • 举报
回复
传值的方式会构造临时对象 也就是所谓的“副本” 操作都是针对这个临时对象的

所以才会有给函数传递参数 尤其是“大对象” 要使用const引用来避免 构造临时对象的一系列开销
moany 2005-11-24
  • 打赏
  • 举报
回复
char *GetMemory3(int num)
{
char *p = (char *)malloc(sizeof(char) * num);//分配一段内存
return p; //把分配到的内存的地址传出来
}

str = GetMemory3(100) //str 得到一个地址,这个地址指向了一段大小为sizeof(char) * num的内存
bing_huo 2005-11-24
  • 打赏
  • 举报
回复
函数用传值的方式传递参数 在函数内对参数的修改不会影响外部的参数本身
用指针和引用传递参数 在函数内部对参数的修改直接影响函数外的参数
thisisll 2005-11-24
  • 打赏
  • 举报
回复
那他说的副本就是用来放值的?
似乎明白了些
可又自己说不清楚
lzp229 2005-11-24
  • 打赏
  • 举报
回复
是不是指针都一样的。
后面那个例子return P回来,用str 接受,这样str 就指向那块动态申请的区域了。
如果不return ,这样申请内存跟主函数里的str没有关系。
寻开心 2005-11-24
  • 打赏
  • 举报
回复
整数变量也好,指针变量也好,是一样的

作为指针的时候,虽然指针本身的数值不会改变,但是指针指向的地址的内容是可以改变的
因为指针作为数值参数传递进入函数体后,函数找不到指针变量的位置,但是可以找到指针指向的地址(这个地址作为数值已经传递进来了),所以可以对地址内的数据进行修改;
这个修改本身实际上和函数体外的指针变量也没有关系;
dragonzxh 2005-11-24
  • 打赏
  • 举报
回复
为什么指向指针的指针就可以了.因为将双重指针**p的内容传递到了函数中,就是把&p传递给函数.函数内部改变指针的内容,这样p就申请了内存 .
寻开心 2005-11-24
  • 打赏
  • 举报
回复
就是c/c++当中的行参还是值参的问题, 和是否是指针没有什么关系


fun(int i) {
i = 100; // 这里对i无论如何修改,也只是在函数体内有效
}

int k = 10;
fun(k);
函数运行返回后, k依然是10
因为在调用fun的时候,并不是把k这个变量传递进去了,而是把k变量对应的数值传递进去了
所以在fun内部对那个数值如何修改已经和k没有关系了

上面说的指针的例子也是一样,只是类型不同而已

64,652

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧