季大哥,帮帮我!

aliker 2003-10-15 07:58:41
先看下面的代码
#include <iostream.h>
#include <conio.h>

void Func1(char *str)
{
str = "Hello!";
}

void Func2(char * * str)
{
* str = "Hello!";
}

void Func3(char * & str)
{
str = "Hello!";
}

void main()
{
char *str1= "AAA" ;
Func1(str1);
cout<<str1<<endl; //str1等于AAA,看起来好象是指针传递,因为字符串本身是指针,所以是值传递

char *str2= "BBB" ;
Func2(&str2); //取地址
cout<<str2<<endl; //str2等于Hello!,看起来好象是指针的指针传递,因为字符串本身是指针,所以是指针传递

char *str3= "CCC" ;
Func3(str3);
cout<<str3<<endl; //str13等于Hello!,看起来好象是指针的引用传递,因为字符串本身是指针,所以是引用传递

}
为什么是指针传递而起不到的作用,难道指针在这里失效了吗?我猜Func1传递的只是指针的值,但是C++怎么区分是指针还是指针的值呢?
...全文
101 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
LanceX 2003-10-20
  • 打赏
  • 举报
回复
当用引用传递时,产生引用的副本,不产生值的副本?

没有产生引用的副本。
quickreport 2003-10-17
  • 打赏
  • 举报
回复
Come on....
TopCoderONE 2003-10-17
  • 打赏
  • 举报
回复
设有char* str, str的地址为0x00aa ,地址0x00aa中内容为0x00bb,则在0x00bb开始处为字符串"fffff\0";所以*str="fffff";

在func1中,传递的内容是0x00bb,在函数中,str的地址为堆栈中的某一地址,反正不是0x00aa,假设是0x00EE,则在地址0x00EE中存放了0x00bb,所以此时如果你取*str,则还是"fffff",但是你赋值str="HELLO",只是改变了0x00EE中的内容。而从0x00bb开始的内容不变,所以等函数返回后,你会发现*str未变。这就是原因所在。
 在func2中,因为你使用了取地址符,所以传递的内容是0x00aa,而函数中*str就是*(0x00aa),取出的值是0x00bb,所以你改变它就是改变了0x00bb中的内容,所以你的函数改变了str的值,不过这是一个很危险的行为,如果你给str分配的空间不够,就会产生错误。
 func3中,你告诉编译器,要传递str的地址,编译器自己找到了str的地址,在func2中是你给了str的地址来传递所以最后结果就一致了。
 其实,在C/C++中,参数传递总是传值的,所以你只要明确函数会传递进去什么值,就不会对指针传递有疑问了。
GeoPhoenix 2003-10-17
  • 打赏
  • 举报
回复
建议你去看一下林锐写的《高质量C++/C编成指南〉里面比较详细的解释了你的问题,因为我只有PDF般的,帖不上来,打字有太多,如果感兴趣,mailto: tiange@email.jlu.edu.cn
我给你发一份
aliker 2003-10-17
  • 打赏
  • 举报
回复
是这样理解吗?
不论是值、指针、引用(只要是形参)都会产生副本
当用值传递时,产生值的副本
当用指针传递时,产生指针的副本,不产生值的副本
当用引用传递时,产生引用的副本,不产生值的副本
void Func1(char str)
void Func1(char *str)
void Func1(char &str)
它们都产生str的副本,对吗?
只不过只有第一个函数产生的是值的副本。只有它不会修改值。对吗?
在下列情况下不用值传递
1、当对象很大,比如一个很大的结构。当用值传递,效率太低。
2、当要修改对象的值时。
3、有的对象本身就是指针的形式。(如char *,BCB的VCL对象)
jiangchun_xn 2003-10-17
  • 打赏
  • 举报
回复
值传递要生成形参的副本,而指针或引用不会。对于上述的Func1和Func2,是指针传递吗?会生成形参的副本吗?

指针也是由副本的,本质是一个整数,你修改这个整数的地址对应的内容,对应的内容就变化了,指针本身不变,搂住估计陷入某个死胡同了。
LanceX 2003-10-17
  • 打赏
  • 举报
回复
1、先说Func1和Func3的区别,
Func1是传值,值传递要生成形参的副本。
Func1(str1);
void Func1(char *str)
{
str = "Hello!";//此处str只是str1的副本,并不是str1本身,所以str虽然指向了"Hello!",但是str1没有变
}
Func3是传址,就是传形参本身
Func3(str3);
void Func3(char * & str)
{
str = "Hello!";//str就是str3本身,所以str指向了"Hello!",str3也指向了"Hello!"
}

2、再说Func2
Func2也是传值
Func2(&str2);
void Func2(char * * str)
{
*str = "Hello!";//str是&str2的副本,但是str和&str2指向的值(其实还是地址)相同,即*str = *(&str2)=str2;
实际上把str指向的值(*str指针)指向了"Hello!",因此也将str2指向了"Hello!"。

}
aliker 2003-10-16
  • 打赏
  • 举报
回复
我并不只是针对季大哥,其他的观众如果会的话也可以发表观点。大家互相学习,互相进步!
aliker 2003-10-16
  • 打赏
  • 举报
回复
为什么没有一个回答能让我满意?
void Func1(char *str)
{
str = "Hello!";
}

void Func2(char *str)
{
*str = 'a';
}
void main()
{
char *str1="abc";
char ch='s';
char *p=&ch;
Func1(str1);
Func2(p);
cout<<str1<<endl; //str1="abc"
cout<<ch<<endl; //ch等于'a'
两个函数看似相同,形式参数,返回类型,调用方式。
但是很显然Func1执行后str1没有变化,而Func2执行后,ch发生了变化(我猜的,我现在没有电脑),为什么呢?因为在Func1中只是对指针值进行了操作,没有涉及到指针指向的变量,也即只是对指针进行访问;而Func2中是对指针值指向的变量进行了间接引用,也即对变量进行访问,修改的是变量。
但我不明白的是:
值传递要生成形参的副本,而指针或引用不会。对于上述的Func1和Func2,是指针传递吗?会生成形参的副本吗?
jiangchun_xn 2003-10-16
  • 打赏
  • 举报
回复
是哦。
zxy_net 2003-10-16
  • 打赏
  • 举报
回复
我才不理你,你只叫了季大哥……
yhz 2003-10-15
  • 打赏
  • 举报
回复
结果正常。

在子函数中:str = "Hello!"; 这句话其实就是修改指针的指向地址,
使它指向一个新的存有"Hello!"的内存块的首地址。

而你在 Func1 中的调用方式其实是把主函数中的 str1 指针在 func1 函数中复制一份,
使两个指针的指向地址为一样。
所以,你在 func1 中对 str 的修改不会影响主函数的 str1 指针的指向。

但是你在 func2 和 func3 函数的调用方式就不同了:
它是在子函数中新建一个指针,然后把这个指针指向主函数的指针的地址,
所以,在这两个函数中修改 *str(str),实际上就等于修改了主函数的指针的指向。
如果你用 printf 函数的 %u(好像是吧?)参数,
就可以看到在调用 func2 和 func3 的前后,str2 和 str3 这两个指针指向的地址改变了。

其实这就是二重指针的作用。


ThinkX 2003-10-15
  • 打赏
  • 举报
回复
你的结果很正常啊。

void Func1(char *str)
{
str = "Hello!";
}

中,编译器会先在栈上复制一个str压栈,所以你不可能改写str的值。
在C中char *str不是很好理解,你要理解为char* str更好,强调了str就是一个指针(win32下一个指针就是一个DWORD值而已),你所说的指针和指针的值其实就是一回事。
zihan 2003-10-15
  • 打赏
  • 举报
回复
其实我觉得还是传递的指针,你可以用strcpy(str, "Hello");来代替 str = "Hello!";试试.

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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