【问题标题】:java vs C++ pass by referencejava vs C++ 通过引用传递
【发布时间】:2011-04-21 15:20:15
【问题描述】:


我对以下内容感到困惑:
在 C++ 中,我们可以通过引用将参数传递给函数(已将其声明为指针或引用变量),如果我们在函数内部对其进行修改,则更改会在函数返回时反映给调用者。
这在 java 中没有发生,我不确定我理解为什么。

例如这是来自对象 X 的方法

public boolean aMethod(int id, myClass aClass)
{
   //do some logic
   aClass = new MyClass();
   //configure argument object aClass
   return true;
}

调用代码中:

//some code processing
myClass obj = null;
if(X.aMethod(2,obj))
{
  obj.methodA();//start using the object
}

我在C++中使用它,即返回一个通知函数参数可以使用的结果,但是在java中这不起作用。
我进入 if(X.aMethod(2,obj)) 分支,但 obj 为空。为什么它是空的?
我不是在方法aMethod(int id,myClass aClass)中使用new从堆中分配了一个内存地址吗?我没有在函数中传递 obj 的“地址”吗? 我期望在调用代码中正确构造和使用 obj。我对 java 中的内存有什么误解吗?

【问题讨论】:

标签: java c++ function pass-by-reference


【解决方案1】:

Java 通过值传递所有内容 - 包括引用

这意味着如果你传递一个对象,你可以修改那个对象的properties,并且在你返回后它们会一直存在,但是你不能替换整个对象带有一个全新的对象,因为您实际上无法修改 reference - 只能修改引用指向的内容。

在您的aClass = 行之前:

Outside the function:

    obj ---> <foo>

Inside the function:

    aClass ---> <foo>

在您的aClass = 行之后:

Inside the function:

    aClass ---> <bar>

Outside the function:

    obj ---> <foo>

这里要注意的关键是aClass 不指向obj - 它指向&lt;foo&gt;。你没有传递obj 的地址,你传递的是obj 指向的地址。因此,当您更改 aClass 指向的内容时,不会触及 obj


作为另一种思考方式:

在 Java 中,

Bar foo = new Bar();

相当于C++,

Bar *foo = new Bar();

因此,当您将foo 传递给函数时,您并没有传递foo 的地址——您传递的是已分配对象的地址。 Java 没有 C/C++ 所具备的 &amp;-operator 样式的传递引用。

【讨论】:

    【解决方案2】:

    查看我的文章“Java 是按值传递,该死”

    http://javadude.com/articles/passbyvalue.htm

    【讨论】:

    • 我的荣幸!很高兴你喜欢它!
    【解决方案3】:

    在 C++ 中,如果你这样做会发生什么:

     void myFunct( int * pInt) {
         pInt = // something;
     }
    
     // caller
     int x;
     int * myPointer = & x;
     myFunc(myPointer);
     // where does myPointer point now? 
    

    myFunc 中的赋值对调用者的指针没有影响。现在如果 myFunct 取而代之的是指向指针的指针

     void myFunct( int ** ppInt) {
         *ppInt = // something;
     }
    

    或者对指针的引用,那么你会看到调用者发生了变化,这就是我想你一直在做的事情。

    在 Java 中

     void myFunct (Integere anInteger) {
           // anInteger is  reference to whatever is passed
           anInteger = new Integer(99); // no effect on caller
     }
    

    我们确实传递了对函数的引用,上面的 anInteger 是对调用者拥有的对象的引用,但是 anInteger 是分配给它的方法的本地值,与第一个示例中分配给 pInt 相同,对调用者没有影响。

    【讨论】:

      【解决方案4】:

      您示例中的注释表明存在 aMethod 方法来配置对象。因此,与其传入 null,不如先实例化对象,然后再传入。或者,您可以使方法返回对象 intead,如下所示:

      public boolean aMethod(int id)
      {
        myClass aClass = new MyClass();
        return myclass;
      }
      

      还有:

      myClass obj = X.aMethod(2);
      if(obj != null)
      {
        obj.methodA();//start using the object
      }
      

      另外,我更喜欢将aMethod 作为一个约定,它应该总是返回一个有效的对象。如果不可能,例如由于配置错误,请让方法抛出异常。

      【讨论】:

        【解决方案5】:

        Java 不能“通过引用传递”。

        Java 使用“按值传递”。

        【讨论】:

        • 您的回答没有提供任何新内容(基本上是重复其他人已经详细说过的内容)并且还会混淆/误导人们。尽管 Jave 使用“按值传递”,但人们仍然可以更改传递对象的属性。但是他们不能重新分配一个全新的对象(OP想要做的)。
        【解决方案6】:

        考虑您的对象参数(在 Java 中)按原样传递(用 C++ 说明):

        void method(TObject* arg);
        

        【讨论】:

        • 应该是void method(TObject*&amp; arg); ?
        • @Ishtar 不,void method(TObject*&amp; arg) 是对指针的引用。 arg 可以在内部修改(指向另一个地址),并将在外部反映——这样当method(arg) 返回时,客户端的 arg 可以指向另一个地址。 Java将对象作为指针/按地址传递。 Java 开发人员喜欢将其称为“按值”,但从 c++ 的角度来看,它是通过指针(或地址)传递的,而语言抽象了这一事实(以及指针)。继续...
        • @Ishtar 第 2 部分:在 C++ 中,按值传递 == 传递对象的副本。这里没有 Java 的副本。因此以 c++ 语法传递 Java 对象类似于:void method(TObject* arg);
        • 对不起。我一定是误会了,我的英语不是那么好.. 以为你的意思不同。事实上,Java 中的 method(T a) 与 C++ 中的 method(T * a) 相同。但是,OP 想要在方法中执行的操作:aClass = new MyClass(); 需要 &amp;。我以为你是这个意思。
        • @Ishtar 没问题。事实上,我最初的回答缺乏细节——所以现在已经澄清了很好。谢谢 =)
        猜你喜欢
        • 2012-06-04
        • 2012-03-13
        • 2011-05-02
        • 2011-01-17
        • 2020-04-01
        • 1970-01-01
        • 2014-03-10
        • 2012-06-14
        相关资源
        最近更新 更多