Java 与 C++ 中的值传递和引用传递解析
先说结论:Java 只有值传递,而 C++ 既有值传递又有引用传递。
Java 的参数传递
先定义 3 个方法如下:
1public static void change1(String str, int num) {
2 str = "world"; // 这里就相当与新 new 了一个对象!
3 num = 100;
4}
5public static void change2(User user) {
6 user.age = 1;
7 user.name = "mary";
8}
9public static void change3(User user) {
10 user = new User(1, "mary");
11}
进行测试:
1public static void main(String[] args) {
2 String str = "hello";
3 int num = 1;
4 System.out.println(str + " " + num); // hello 1
5 change1(str, num);
6 System.out.println(str + " " + num); // hello 1
7
8 System.out.println("------------------");
9
10 User user = new User(123, "peter");
11 System.out.println(user.name + " " + user.age); // peter 123
12 change2(user);
13 System.out.println(user.name + " " + user.age); // mary 1
14
15 System.out.println("------------------");
16
17 user = new User(123, "peter");
18 System.out.println(user.name + " " + user.age); // peter 123
19 change3(user);
20 System.out.println(user.name + " " + user.age); // peter 123
21}
由 change2 和 change3 可知,对于引用类型,java 是值传递,在函数中只能改变形参对应的实参所引用的对象,而无法改变实参本身,也就是说形参传递的是实参所引用的对象,而不是实参本身。
由 change1可知,对于基本数据类型,java 是值传递。
对于 String 类型,应作特殊理解:String 本身属于引用类型,String 底层由 char 数组维护,是final 类型的,本身是不可改变,通过 “=” 赋值即相当于通过 new 新创建了一个对象,本质就是 change3 的操作。
C++ 的参数传递
解释了 java 的参数传递,可能会陷入困惑,到底什么才是引用传递呢?
我们再来看看 C++ 的参数传递:
定义 2 个方法如下:
1void change1(User* user) {
2 user->age = 999;
3 user->name = "mary";
4}
5void change2(User* user) {
6 user = new User(999, "mary");
7}
进行测试:
1User* user1 = new User(21, "peter");
2cout << user1->age << " " << user1->name << endl; // 21 peter
3change1(user1);
4cout << user1->age << " " << user1->name << endl; // 999 mary
5
6User* user2 = new User(21, "peter");
7cout << user2->age << " " << user2->name << endl; // 21 peter
8change2(user2);
9cout << user2->age << " " << user2->name << endl; // 21 peter
这样的效果和 java 测试中的 change2 和 change3 是一致的,都是传递了实参引用的对象!
下面看看如何实现引用传递吧:
这里形参就传递了实参本身!
1void change3(User*& user) {
2 user = new User(999, "mary");
3}
测试如下:
1User* user3 = new User(21, "peter");
2cout << user3->age << " " << user3->name << endl; // 21 peter
3change3(user3);
4cout << user3->age << " " << user3->name << endl; // 999 mary
可见在函数中实现了对形参所对应实参本身的修改!
为什么 Java 取消了引用传递
应该是为了更简单,更安全的开发吧。
函数调用无法修改实参,这样一定程度上避免了很多错误的发生,但同时限制了可以做的事情,可以说有利有弊。