Java和C++;按值传递和按引用传递

Java和C++;按值传递和按引用传递,java,c++,Java,C++,据说,在Java方法中,参数是按值传递的,这对于原语和对象都是如此,对象的引用是按值传递的。为了说明代码考虑: class Test { private static void dateReplace (Date arg) { arg = new Date (arg.getYear(), arg.getMonth(), arg.getDate() +1); System.out.println ("arg in dateReplace: " + arg);

据说,在Java方法中,参数是按值传递的,这对于原语和对象都是如此,对象的引用是按值传递的。为了说明代码考虑:

class Test {
 private static void dateReplace (Date arg) {
        arg = new Date (arg.getYear(), arg.getMonth(), arg.getDate() +1);
        System.out.println ("arg in dateReplace: " + arg);
    }

 public static void main(String[] args) {

      Date d1 = new Date ("1 Apr 2010");
        dateReplace(d1);
        System.out.println ("d1 after calling dateReplace: " + d1);
    }
}

this will print:
arg in dateReplace: Fri Apr 02 00:00:00 2010
d1 after calling dateReplace: Thu Apr 01 00:00:00 2010.
<>什么是给出相同结果的C++等价物?< /P>

什么是C++等价的,在调用方法与方法内的值相同时,它给出D1的值,即调用方看到修改后的值?p>

class Test {
 void dateReplaceReference(Date& arg) {
   // arg is passed by reference, modifying arg 
   // will modify it for the caller
 }
 void dateReplaceCopiedArgument(Date arg) {
   // arg is passed by value, modifying arg 
   // will not modify data for the caller
 }
 void dateReplaceByPointer(Date* arg) {
   // arg is passed as pointer, modifying *arg 
   // will modify it for the caller
 }
};

请注意,作为引用传递或通过指针传递是一样的。唯一的区别是您希望通过“.”或“->”访问数据的方式。此外,不能将空值传递给引用的方法。

C++默认按值传递。您可以通过编写函数以接受引用来隐式传递引用,也可以通过传递指针来显式传递引用

考虑以下三个例子:

FooByValue(Foo arg)
{
  //arg is passed by value.
}

FooByReference(Foo & arg)
{
  //arg is passed by reference.
  //changes made to arg will be seen by the caller.
}

FooByPointer(Foo * arg)
{
  //arg is passed by reference with pointer semantics.
  //changes made to the derefenced pointer (*arg) will be seen by the caller.
}
然后,您可以按如下方式调用上面的 Foo-anObject

FooByValue(anObject); //anObject will not be modified.
FooByRefence(anOBject); //anOBject may be modified.
FooByPointer(&anObject); //anObject may be modified.
当应用于变量(如
&anOBject
)时,&符号用于获取变量的地址,基本上给出一个指向该变量存储在内存中的位置的指针


FooByValue()
的操作与您的示例类似,并且
FooByReference()
将保留函数调用后对参数所做的任何更改,因为参数不会被复制,它在内存中的实际位置将被共享。

C++在值和引用方面与Java没有相同的语义。首先,每个类型都有可能通过复制、引用或地址传递(但是,可以通过隐藏复制构造函数来防止通过复制传递类型)

与Java的“按引用”传递最密切相关的传递类型是指针传递。以下是三个方面的示例:

void foo(std::string bar); // by copy
void foo(std::string& bar); // by reference
void foo(std::string* bar); // by address
作为旁注,对于大于指针大小的类型,通过副本传递总是比通过引用或指针传递更昂贵。出于这个原因,您也可能更喜欢通过
const
reference传递,这将允许您读取对象而无需复制它

void foo(const std::string& bar); // by const reference
<>但是,这是很棘手的,你需要知道java的细微差别来正确决定C++中你想要什么。在Java中,实际上并不是通过引用传递对象:而是通过副本传递对象引用。也就是说,如果将新对象指定给参数,则父范围的对象不会更改。在C++中,通过地址比引用更接近匹配对象。下面是一个例子,说明了这一点的重要性:

// Java using "object references":
public static void foo(String bar)
{
    bar = "hello world";
}

public static void main(String[] argv)
{
    String bar = "goodbye world";
    foo(bar);
    System.out.println(bar); // prints "goodbye world"
}

// C++ using "references":
void foo(std::string& bar)
{
    bar = "hello world";
}

int main()
{
    std::string bar = "goodbye world";
    foo(bar);
    std::cout << bar << std::endl; // prints "hello world"
}

// C++ using pointers:
void foo(std::string* bar)
{
    bar = new std::string("goodbye world");
    delete bar; // you don't want to leak
}

int main()
{
    std::string bar = "goodbye world";
    foo(&bar);
    std::cout << bar << std::endl; // prints "hello world"
}
//Java使用“对象引用”:
公共静态void foo(字符串栏)
{
bar=“你好,世界”;
}
公共静态void main(字符串[]argv)
{
字符串栏=“再见世界”;
富(巴);;
System.out.println(bar);//打印“再见世界”
}
/C++使用“引用”:
void foo(标准::字符串和条形)
{
bar=“你好,世界”;
}
int main()
{
std::string bar=“再见世界”;
富(巴);;
std::cout
运算符访问成员,以及使用运算符重载带来的额外复杂性

另一个显著的区别是,由于按引用参数的使用在语法上与按复制参数的使用密切相关,因此函数应该能够假定按引用传递的对象是有效的。尽管通常可以将引用传递给
NULL
,但这是非常不鼓励的,因为唯一的方法是取消引用具有未定义行为的
NULL
。因此,如果您需要能够将
NULL
作为参数传递,则更愿意按地址传递参数,而不是按引用传递参数


大多数情况下,当您想修改函数中的参数时,您会希望通过引用而不是通过地址传递,因为它更“C++友好”(除非您需要
NULL
值),即使它与Java的功能不完全一样。

这是家庭作业吗?您可能想阅读C的*(间接)和&(引用)运算符。@ Eggaya,C和C++都没有引用操作符,并且是操作符的地址。@ Unpss:有什么区别?s@eggyval在C++中,你处理指针和引用的方式不同。<代码>和Foo< /Cord>让你得到指针“<代码> Foo”,处理它将要求你使用指针语法。(例如,您必须使用
->
运算符访问成员)。当您通过引用传递对象时,它与值完全相同(您使用
运算符访问成员)“艾伦,这是很多年前我试图找出面向对象编程的时候,我终于在汇编程序中看到它是如何实现的。为了实现C++中的java,你只需要通过指针传递值和对象来传递原语。因为没有明确的GC,如果发生了,你可能需要释放/删除对象。创建一个错误。没有任何东西在C++中被引用。这是一个常见的误解。你通过值传递一个引用/指针。如果它被引用传递,你可以修改参数本身(而不仅仅是它指向/引用的对象)。@ Tamas,你似乎对“通过引用”这个词有自己的私人意义。@ TAMAS是的,它和C++的方式完全一样。在链接到的代码的参数列表前面,你看到了<代码> var >代码,这与在C++中声明一个参数是完全一样的。默认情况下,不使用var,Pascal是通过值。在C++中??我错了。谢谢你以一种尊重、平静的方式解释它。现在我不明白。正如你第一次说的,我把java参考语义与C++中的一个混淆了。再次感谢。实际上,修改<代码> *ARG< /Calp>会修改调用方中的数据。修改<代码> ARG不会。是的。通过指针进行操作将更改所有用户的对象。使更改不可见的唯一方法是第二种方法,