传值和传引用
-
传值 vs. 传引用
- java和python只支持传值(pass by value)
- c++和c#两者都支持
-
传变量的测试
在java/c++/c#中测试以下代码:
java实现:
/* * @Author: sanjayzhong * @Github: https://github.com/sanjayzzzhong * @Date: 2019-09-06 13:58:40 */ public class test_object { public static void main(String[] args) { int a = 1; foo(a); System.out.println(a); } public static void foo(int x){ x += 1; } }
运行输出为
1
用c++实现:
#include <iostream> #include <cassert> using namespace std; void foo(int x){ x += 1; } int main() { int a; a = 1; foo(a); assert(a == 2); return 0; }
运行结果如下:
a.out: test_value.cpp:14: int main(): Assertion `a == 2' failed. [1] 9284 abort ./a.out
也就是a的值没有改变。
a和x都是在栈生成的:
地址 变量值 变量名 1004 2 x 1000 1 a
如果用c++的引用来使函数的值改变,则如下:
/* * @Author: sanjayzhong * @Github: https://github.com/sanjayzzzhong * @Date: 2019-09-06 13:38:34 */ #include <iostream> #include <cassert> using namespace std; void foo(int &x){ //c++ reference x += 1; } int main() { int a; a = 1; foo(a); assert(a == 2); return 0; }
运行没有出现任何东西,说明a已经改变为2了。
来看一下引用的内存变化:
地址 变量值 变量名 1004 #1000(存的值是地址) x 1000 1 a 其实c++中的引用本质上是用指针来实现的,可以认为引用是指针的语法糖。
语法糖(Syntactic sugar)是由英国计算机科学家彼得·蘭丁发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。
上面代码与下面的代码完全等价(但有些区别):
/* * @Author: sanjayzhong * @Github: https://github.com/sanjayzzzhong * @Date: 2019-09-06 13:38:34 */ #include <iostream> #include <cassert> using namespace std; void foo(int *x){ //c++ pointer (*x) += 1; } int main() { int a; a = 1; foo(&a); assert(a == 2); return 0; }
具体区别:
- 引用不能为NULL
- 在foo函数中引用x不能指向其他对象
引用不仅仅是语法糖,而且比指针的限制更多。
-
传对象object的测试
java代码
/* * @Author: sanjayzhong * @Github: https://github.com/sanjayzzzhong * @Date: 2019-09-06 14:05:23 */ public class TestObject { public static void main(String[] args) { int a = 1; foo(a); System.out.println(a); } public static void foo(Integer x){ x += 1; } }
最后运行,得到的结果为
1
也就是说,传object没有改变a的值。其实上面的关键代码中,java进行了拆箱和装箱的操作:
void foo(Integer x){ int v = x; //拆箱 v += 1; v = new Integer(v); //装箱 }
-
怎么通过传值来修改值呢(pass-by-value)
-
用数组的形式(array)
# -*- coding: UTF-8 -*- ''' @Author: sanjayzhong @Github: https://github.com/sanjayzzzhong @Date: 2019-09-06 14:18:41 ''' def foo(x): x[0] += 1 a = [1] foo(a) assert(a[0] == 2)
-
用类成员(class member)
# 暂时没懂 留坑
-