LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 5579|回复: 15

c/c++ 中的传值调用和传引用,我的理解.

[复制链接]
发表于 2003-7-30 02:13:14 | 显示全部楼层 |阅读模式
请多指教,最好把我驳的体无完肤.

  1. // Reference.cpp
  2. // Different between pass by Reference and pass between value
  3. #include <iostream>
  4. using namespace std;

  5. void f(int&, int);

  6. main()
  7. {
  8.         int i = 0, j = 0;
  9.         cout << "i= " << i << "\t" << "j= " << j << endl;
  10.         cout << "&i= " << &i << "\t" << "&j= " << &j << endl;
  11.         f(i, j);
  12.         cout << "i= " << i << "\t" << "j= " << j << endl;
  13. //        wait();
  14.         return 0;
  15. }

  16. void f(int& x, int y)
  17. {
  18.         cout << "x= " << x << "\t" << "y= " << y << endl;
  19.         cout << "&x= " << &x << "\t" << "&y= " << &y << endl;
  20.         x++;
  21.         y++;
  22.         cout << "x= " << x << "\t" << "y= " << y << endl;
  23. }
复制代码

屏幕输出:

i= 0    j= 0
&i= 0x22ff6c    &j= 0x22ff68
x= 0    y= 0
&x= 0x22ff6c    &y= 0x22ff44
x= 1    y= 1
i= 1    j= 0

可以看到给函数 f() "传引用(pass by reference)"和"传值(pass by value)"在使用上类似,但实际中有很大区别:

"传值"传递的是原始变量 j 的一份拷贝 y,编译器为新的拷贝 y 重新分配了内存空间,因此本例中变量 j 和 变量 y 有不同的内存地址.对函数 f() 体内 y 的附新值,不会影响函数 f() 体外 j 的值.

"传引用"传递的是变量 i 的地址,并没有额外分配新的内存空间.x 就相当于 i 在 f() 体内的一个别名(我的理解),x 同 i 使用相同的地址空间,使用 x 就相当于引用了 i 的值,显然对 f() 体内 x 赋新值,就会影响到函数 f() 体外 i 的值.这点其实也就是我们使用"传引用"的目的之一,能影响 "outer object".

有的时候你希望引用函数如 f() 不能修改被引用的变量如 i,那么可以这样定义函数:
void f(const int& x, int y)

这样的话,如果你还是在 f() 里使用 x++,那么编译时就会提示你引用的是一个只读变量.

这是一种良好的编程习惯, 比起传值调用,优点在于不需要额外分配内存空间.

本例 c 源码:

  1. /* Reference.c                                                */
  2. /* Different between pass by Reference and pass between value */
  3. #include <stdio.h>

  4. void f(int& i, int j);
  5. main()
  6. {
  7.         int i = 0, j = 0;
  8.         printf("&i=%x, &j=%x\n", &i, &j);
  9.         f(i, j);
  10.         printf("i=%d, j=%d\n", i, j);
  11.         return 0;
  12. }

  13. void f(int& i, int j)
  14. {
  15.         printf("&i=%x, &j=%x\n", &i, &j);
  16.         i++;
  17.         j++;
  18. }
复制代码
发表于 2003-7-30 03:05:40 | 显示全部楼层
Good article.

However you seem not familar with C.  To pass by reference in C, the only way is using pointers.  Parameters such as ``int& a'' doesn't work in C, at least not in C89.
 楼主| 发表于 2003-7-30 09:06:14 | 显示全部楼层
说的对。忘了说明我正在学 C++.
发表于 2003-7-30 09:39:56 | 显示全部楼层
Are you interested in C?  I think I can give a correct C example.
发表于 2003-7-30 09:47:56 | 显示全部楼层
不错。

传引用只有在传递对象时才有优势,引用本身也需要4个字节的空间,和int是一样的,所以传int是不应该使用引用的。
发表于 2003-7-30 10:13:31 | 显示全部楼层
收获不少。
发表于 2003-7-30 10:49:49 | 显示全部楼层
引用实际上是一个常量指针,不会再指向别的对象。但在作为函数参数时,特别是在涉及对象时,引用比指针和传值有优势。如果对象采用传值方式传递,必然会调用自身的构造函数和并递归调用基类的构造函数。如果继承的层次多,这会造成很大的开销。但是在使用指针时,又会发生对象切片问题,所以在传递对象时,最好使用安全和高效的引用。
发表于 2003-7-30 13:04:09 | 显示全部楼层
最初由 kj501 发表
引用实际上是一个常量指针,不会再指向别的对象。但在作为函数参数时,特别是在涉及对象时,引用比指针和传值有优势。如果对象采用传值方式传递,必然会调用自身的构造函数和并递归调用基类的构造函数。如果继承的层次多,这会造成很大的开销。但是在使用指针时,又会发生对象切片问题,所以在传递对象时,最好使用安全和高效的引用。


请问一下什么叫对象切片问题?从来没有听过。
 楼主| 发表于 2003-7-30 13:35:44 | 显示全部楼层
最初由 高原之狼 发表
Are you interested in C?  I think I can give a correct C example.


谢谢你的帮助,多多益善。
发表于 2003-7-30 13:59:59 | 显示全部楼层
最初由 pupilzeng 发表
请问一下什么叫对象切片问题?从来没有听过。

指在多态使用对象时,派生类对象在复制过程中发生向上类型转换,使得本来应该复制的是派生类对象,结果却只复制了派生类对象的基类对象部分,相当于派生类对象被切掉了一部分。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表