C++和JAVA传值和传引用分析

本文通过示例代码详细对比了C++与Java中参数传递的不同方式,包括C++中的传值、传址和引用,以及Java中的“引用传递”。通过直观的图形解释了这些传递方式的内部机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家对C++中的引用和传值函数调用应该不陌生。然而,初次接触Java后,被这个问题着实
迷惑了一阵子。在看了IBM的Java园地中相关的文章后,有些想法,大胆讲出来,希望能听
到不同的声音。
在C++中,有三种参数传递方法,一种是传值、一种是传址、一种是引用。下面分别列出这
三种的情形:
//传值调用swap
void swap(int a,int b)
{
        int tmp = a;
        a = b;
        b = a;
}
void swap2(int * a,int *b)
{
        int tmp = *a;
        *a = *b;
        *b = tmp;
}
void swap3(int &a,int &b)
{
        int tmp = a;
        a = b;
        b = tmp;
}
int main(int argc,char **argv)
{
        int a = 3;
        int b = 5;
        swap(a,b);
        swap2(&a,&b);
        swap3(a,b);
}
内部机制用图形表示比较直观一点:(变量地址是假设的,依情况不同而变化)
/*****************main中**********************/
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                   0x71FE
****************函数swap中********************
变量名       a                                              b
值             3                                              5
内存地址    0x9200                                   0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                   0x91FE
/********************************************/
可以看出,由于C++中的传值调用问题,所以虽然swap(int,int)函数中的局部变量a,b的值
改变了,但因为此a,b与main中的
彼a,b是内存中的不同存储单元,所以对main中的变量毫无影响。swap(int,int)不能完成
交换的任务。
/*****************main中**********************/
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                   0x71FE
****************函数swap2中********************
变量名       a                                              b
值             0x7200                                   0x71FE
内存地址    0x9200                                   0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                   0x91FE
/********************************************/
同样分析,由于C++传递参数时始终是传值调用(下面我们将看到,引用也不例外,只是稍
微有点特殊 ),所以,main()函
数中的a和b分别布局在内存中的0x7200和0x71FE处,调用swap2(int *,int *)后,函数sw
ap2(int *,int *)中的局部指针变量a,b的位址是0x9200和0x91FE,然而,其值是0x7200和
0x71FE,分别指向main函数中的a,b。
所以,经过调用后,main函数中的a,b会交换值。函数swap2(int *,int *)可以正常工作。

下面要特别注意,这正是Java和C++不同的地方,也是特别容易混淆的地方。
/*****************main中**********************/
变量名       a                                              b
值             3                                              5
内存地址    0x7200                                   0x71FE
****************函数swap3中********************
变量名       a                                              b
值             0x7200                                   0x71FE
内存地址    0x9200                                   0x91FE
*****************执行完成后**********************
变量名       a                                              b
值             5                                              3
内存地址    0x9200                                   0x91FE
/********************************************/
引用的机制在C++中我不是很清楚,但有一点,它的工作机制非常象指针,只是不用进行解
引用操作。而且,引用不能赋值,只能进行初始化。(请注意这句话)。所以,我们常常
叫它别名。
void swap3(int &a,int &b)
{
        int tmp = a; // a是主函数main中的局部变量a的引用,或者说,指向main中的局部变量
a
        a = b;  //b是主函数main中的局部变量b的引用,或者说,指向main中的局部变量b
        b = tmp;//以上由于引用的特性,所以a=b时,不是说a引用b,而是b的值赋给a,b=tmp是
同样的。
        
        //由于这里的a,b和main中的a,b是同一个东西,所以也完成了交换值的任务。 
}
而java中除了此引用外,同样也是传值,但与其说Java中的引用叫引用,不如称之为指针
。使用下面的java示例可以说明问题
class Swap
{
  public static void main(String args[])
  {
    Integer a, b;
    a = new Integer(10);
    b = new Integer(50);
    System.out.println("before swap...");
    System.out.println("a is " + a);
    System.out.println("b is " + b);
    swap(a, b);
    System.out.println("after swap...");
    System.out.println("a is " + a);
    System.out.println("b is " + b);
  }
  public static void swap(Integer a, Integer b)
  {
    Integer temp = a; //a,b是main方法中的a,b的指针
    a = b;  //a指向b
    b = temp;//b指向a
    
    //因为只有swap方法中的局部参数变量a,b的指针指向变化,所以对main方法中的数值
毫无影响。
  }
}
再举一个更能说明问题的例子,来说明java中的对象引用不同C++一样,只能初始化,而且
可以任意指向的问题(所以我认为更适合称之为“自解引用指针”)。
import java.awt.Point;
public class Assign {
                int a = 1;
                int b = 2;
                Point x = new Point(0,0);
                Point y = new Point(1,1);       
                
        public static void main(String[] args) {
                System.out.println("a is " + a);
                System.out.println("b is " + b);
                System.out.println("x is " + x);
                System.out.println("y is " + y);
                
                System.out.println("Performing assignment and  " + "setLocation...");
                
                a = b; // a == 2
                a ++; // a == 3
                x = y; // x指向y
                x.setLocation(5,5); //x指向的point的值为[5,5],因为x指向y,所以Point y的值也为
[5,5]
                //原来x指向的point(0,0)已经丢失了,象C++中的内存泄露一样,不过不用担心,Java
的垃圾收
                //集器会帮忙料理的,不用担心。
                
                System.out.println("a is " + a);
                System.out.println("b is " + b);
                System.out.println("x is " + x);  // x == [5,5]
                System.out.println("y is " + y); // y == [5,5]
        }
}
好了,现在大家应该清楚Java中的参数传递和所谓的“引用传递”了吧。写了这么多,还
是这么一句话,我个人认为,Java中称对象传递的是引用并不恰当。改成“自解引用指针
”对C/C++程序员可能更好理解。大家认为呢?
<think>嗯,用户想了解Java引用的区别,以及是否存在引用的概念。首先,我得回忆一下Java参数递机制。记得Java里只有,没有引用,不过对于对象类型来说,递的是引用的副本,这可能会让人误解为引用。 然后,用户提到的几个引用资料,特别是引用[3]提到,无论是基本类型还是引用类型,参数都是的。基本类型的是的拷贝,而引用类型的是引用的拷贝。所以当你在方法里修改引用类型的成员变量时,会影响原对象,但如果直接修改引用本身,比如指向另一个对象,原来的实参不会变。这点需要解释清楚。 接下来,用户可能混淆了引用的概念,比如C++中的引用。需要明确说明Java中没有引用,只有,包括对象引用也是。可能还需要举例子,比如修改对象属性会影响原对象,而重新赋引用不会改变原引用。 另外,是否存在引用的概念?其实在Java中并没有这种术语,可能用户是听到过类似的说法,需要澄清这个术语的正确性,指出正确的说法是“引用的拷贝”,即的方式引用。 还要考虑用户可能的误区,比如认为对象参数是按引用递,但实际上只是递了引用的副本。需要强调这一点,避免误解。同时,结合引用[2]的内容,说明修改形参的引用不会影响实参,但修改对象的属性会影响。 最后,确保回答结构清晰,分点解释,并附上示例代码,帮助用户理解。可能还需要生成相关问题,比如参数递在内存中的表现,或者与C++的区别,但用户已经提供了相关问题,可能需要调整。</think>### Java 引用的区别及引用概念解析 #### 一、Java 参数递的核心机制 Java 中**所有参数递均为**(pass-by-value),不存在统意义上的“引用”(pass-by-reference)。但对于对象类型,递的是**对象引用的拷贝**,而非对象本身[^3]。这一机制可通过以下两点解析: 1. **基本数据类型(如 `int`, `double`)** 递的是的副本,方法内修改不会影响原始变量: ```java void modify(int x) { x = 10; } int a = 5; modify(a); // 调用后 a 仍为 5 ``` 2. **引用数据类型(如对象、数组)** 递的是对象引用的拷贝,方法内修改对象属性会影响原对象,但重新赋形参引用不会影响实参: ```java class Person { String name; } void changeName(Person p) { p.name = "Alice"; } // 影响原对象 void resetRef(Person p) { p = new Person(); } // 不影响实参引用 ``` #### 二、引用的概念澄清 “引用”这一术语在 Java 中并不存在,实际是对“递对象引用拷贝”的通俗表述。关键区别在于: - ****:参数的副本(基本类型直接拷贝引用类型拷贝引用地址)。 - **引用(其他语言)**:直接操作原变量地址(Java 不支持此机制)[^2]。 #### 三、示例对比 | 操作类型 | 基本类型参数 | 对象类型参数 | |----------------------|--------------------|------------------------| | 修改参数 | 不影响原 | 不影响原引用指向 | | 修改对象属性/元素 | 不适用 | 影响原对象内容 | | 重新赋参数引用 | 不适用 | 不影响原引用指向 | #### 四、内存模型视角 - **堆与栈的关系**:对象实例存储在堆(heap),引用变量存储在栈(stack)。参时拷贝的是栈中的引用,而非堆中对象[^4]。 - **方法调用过程**:形参接收实参引用的副本,二者指向同一对象,但形参本身是独立变量。 #### 五、常见误区 - **误区 1**:“Java引用” **纠正**:仅引用的拷贝,本质仍是[^3]。 - **误区 2**:“修改形参引用会影响实参” **纠正**:形参重新赋后与原引用解耦,实参不受影响。 --- §§ 相关问题 §§ 1. Java 中 `String` 作为参数时为何表现出“不可变性”? 2. 如何通过内存模型解释方法调用时的对象递? 3. JavaC++参数递机制上有何本质区别?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值