Java和C ++传递值并通过引用传递 [英] Java and C++ pass by value and pass by reference

查看:85
本文介绍了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);
}

public static void main(String [] args){

Date d1 = new Date(2010年4月1日);
dateReplace(d1);
System.out.println(d1 after calling dateReplace:+ d1);
}
}

这将打印:
arg在dateReplace:Fri Apr 02 00:00:00 2010
d1调用dateReplace后:Thu Apr 01 00:00:00 2010.

什么是C ++等效项, p>

什么是C ++等价物,在调用方法之后,使方法的值与方法中的值相同,即调用者看到修改的值?

解决方案

C ++与值和引用不具有与Java相同的语义。首先,每种类型都有可能通过副本或通过引用或地址传递(但是您可以通过隐藏副本构造函数来防止类型通过副本传递)。



与Java的通过引用传递最密切相关的传递类型是通过指针。下面是三个示例:

  void foo(std :: string bar); // by copy 
void foo(std :: string& bar); // by reference
void foo(std :: string * bar); //通过地址

另一方面,通过拷贝传递总是比通过引用传递指针,用于大于指针大小的类型。出于这个原因,你可能还经常喜欢通过 const 引用,这将允许你读取一个对象,而不必复制它。

  void foo(const std :: string& bar); //通过const引用

然而,这是所有棘手的,你需要知道Java微妙在C ++中正确地决定你想要什么。在Java中,你实际上不是通过引用传递对象:你是通过副本传递对象引用。也就是说,如果为参数分配一个新对象,父作用域的对象不会改变。在C ++中,这更匹配传递的对象按地址而不是引用。下面是一个重要的例子:

  // Java使用对象引用:
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); // printgoodbye world
}

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

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

// C ++使用指针:
void foo(std :: string * bar)
{
bar = new std :: string(goodbye world);
delete bar; //你不想泄露
}

int main()
{
std :: string bar =goodbye world;
foo(& bar);
std :: cout<< bar<< std :: endl; // printshello world
}

换句话说, C ++,你真的处理你通过的同一个变量。对它执行的任何更改(甚至是分配)都会反映到父作用域。 (这部分是由于C ++如何处理赋值运算符)。使用指针,你会得到一个与你使用Java引用的行为更接近的行为,代价是可能必须通过一元的方式获取对象地址& 运算符(在我的例子中参见 foo(& bar)),需要使用 > 运算符访问成员,以及使用运算符重载的一些额外复杂性。



另一个显着的区别是,参数在语法上与副本参数的使用密切相关,函数应该能够假定通过引用传递的对象是有效的。即使通常可以传递一个引用 NULL ,这是非常不鼓励的,因为唯一的方法是取消引用 NULL ,它有一个未定义的行为。因此,如果您需要能够传递 NULL 作为参数,您将更喜欢通过地址而不是引用传递参数。



大多数情况下,当你想从函数中修改参数时,你需要通过引用传递而不是按地址,因为它更多的是C ++友好(除非你需要 NULL value),即使它不像什么Java。


It is said that in Java method arguments are passed by value which is true for primitives and for objects, object's reference is passed by value. To illustrate consider the code:

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.

What is the C++ equivalent that would give same results?

What is C++ equivalent that would give the value of d1 after calling the method to be the same value as within the method i.e. the caller see the modified value?

解决方案

C++ does not have the same semantics as Java for values and references. At first, every type has the potential to be either passed by copy or by reference or by address (you can however prevent types to be passed by copy by hiding the copy constructor).

The passing type the most closely related to Java's "by reference" passing is by pointer. Here are an example of the three:

void foo(std::string bar); // by copy
void foo(std::string& bar); // by reference
void foo(std::string* bar); // by address

As a side note, passing by copy is always more expensive than passing by reference or pointer for types that are larger than the size of a pointer. For this reason, you may also often prefer to pass by const reference, which will allow you to read an object without having to copy it.

void foo(const std::string& bar); // by const reference

However, this is all tricky and you need to be aware of Java subtleties to decide correctly what you want in C++. In Java, you're not actually passing objects by references: you are passing object references by copy. That is, if you assign a new object to an argument, the object of the parent scope won't change. In C++, this more closely matches passing objects by address than by reference. Here's an example of how this is important:

// 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"
}

In other words, when you use references in C++, you're really dealing with the same variable you passed. Any change you do to it, even assignations, are reflected to the parent scope. (This is in part due to how C++ deals with the assignation operator.) Using pointers, you get a behavior more closely related to the one you have with Java references at the cost of possibly having to get object addresses through the unary & operator (see foo(&bar) in my example), needing to use the -> operator to access members, and some additional complexity for using operator overloads.

Another notable difference is that since the usage of by-reference arguments is syntactically closely related to the usage of by-copy arguments, functions should be able to assume that the objects you pass by reference are valid. Even though it's usually possible to pass a reference to NULL, this is very highly discouraged as the only way to do it is to dereference NULL, which has an undefined behavior. Therefore, if you need to be able to pass NULL as a parameter, you'll prefer to pass arguments by address rather than by reference.

Most of the time, you'll want to pass by reference instead of by address when you want to modify an argument from a function because it is more "C++ friendly" (unless you need the NULL value), even though it's not exactly like what Java does.

这篇关于Java和C ++传递值并通过引用传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆