Java vs C++ (Call-By-Reference?)

huangapple go评论88阅读模式
英文:

Java vs C++ (Call-By-Reference?)

问题

以下是翻译好的内容:

Java

public static int calculateWinner(int[][] game) {
    game[0][0] = 5;
    // ...
}

public static void main(String[] args) {
    int[][] game = {
        {1, 2, 2},
        {2, 1, 2},
        {1, 1, 1}
    };
    int winner = calculateWinner(game);
    // ...
}

C++

int calculateWinner(array<array<int, 3>, 3> field) {
    field[0][0] = 5;
    // ...
}

int main(int argc, const char* argv[]) {
    array<array<int, 3>, 3> field;
    field[0] = { 2, 0, 1 };
    field[1] = { 0, 1, 0 };
    field[2] = { 1, 0, 2 };
    
    int winner = calculateWinner(field);
    // ...
}

因此,如果我在主方法中打印数组,为什么在 Java 中我的数组在位置 [0][0] 上是 5,但在 C++ 中不是呢?我了解在 C++ 中它只在作用域内进行复制。究竟有什么区别呢?

英文:

I am not sure if this topic is about Call-By-Reference but I have a question about these 2 snippets:

Java

public static int calculateWinner(int[][] game){
		game[0][0] = 5; 
.
.
.
}


public static void main(String[] args) {
		
		int[][] game = {
			{1, 2, 2},
			{2, 1, 2},
			{1, 1, 1}
		};

        int winner = calculateWinner(game);
.
.
.
}

C++

int calculateWinner(array&lt;array&lt;int, 3&gt;, 3&gt; field) {
	field[0][0] = 5;
.
.
.
}

int main(int argc, const char* argv[]) {

	array&lt;array&lt;int, 3&gt;, 3&gt; field;
	field[0] = { 2, 0, 1 };
	field[1] = { 0, 1, 0 };
	field[2] = { 1, 0, 2 };

	int winner = calculateWinner(field);
.
.
.
}

So if I print out the array in the main method, why is it in Java that my array at position [0][0] is 5 but in C++ it's not?
I learned that in C++ it's a copy only in the scope.
What exactly is the difference?

答案1

得分: 4

正如上面所指出的,这里的主要问题是,默认情况下参数是按值传递而不是按引用传递。在Java中也是如此,然而,在Java代码片段中传递的是数组的指针,而不是数组本身,这使其看起来像是“按引用传递”,然而,Java始终是按值传递

在C++中,可以同时按值传递和按引用传递。您可以传递一个对象的指针,这是程序内存中的一个部分,其中包含所需值的位置,或者您可以传递指向存储该值的内存中特定位置的引用。请注意以下代码片段中指针的内存地址

#include <iostream>

void foo(int num)
{
    std::cout << "The location of pass-by-value num is: " << &num << std::endl;
}

void foo1(int* num)
{
    std::cout << "The location of num* is: " << &num << " But its value is: " << num << std::endl;
}

void foo2(int& num)
{
    std::cout << "The location of num& is: " << &num << std::endl;
}

int main()
{
    int num;

    std::cout << "The location of num is: " << &num << std::endl;

    foo(num);
    foo1(&num);
    foo2(num);
}

此片段的输出为:

The location of num is: 0x7ffce8cceccc

The location of pass-by-value num is: 0x7ffce8ccecac

The location of num* is: 0x7ffce8cceca8 But its value is: 0x7ffce8cceccc

The location of num& is: 0x7ffce8cceccc

在函数foo中,我们传递整数的,因此,我们得到的地址与原始地址不同。

在函数foo1中,我们传递了指向num指针的值。指针有自己的内存位置,其num的内存地址。

在函数foo2中,我们传递了对整数num引用,其内存地址恰好是原始内存地址,这是一个真正的按引用传递。

要编辑这样的对象,您需要通过指针或引用来传递它(通常情况下,尽可能使用按引用传递而不是指针)。

英文:

As noted above, the main problem here is that by default, the parameters are passed as values and not references. It is true in Java as well, however, whatever passed in the java snippet is the pointer to the array, and not the array itself, making it seem as "pass by reference", however, Java is always passing by value!

In C++ it is possible to pass both by value and by reference. You can pass a pointer to an object, which is a new section in the program's memory, which contains the location to the wanted value, or you can pass the reference to the specific position in the memory in which the value is stored. Notice the memory addresses of the pointer in the following code snippet:

#include &lt;iostream&gt;

void foo(int num)
{
    std::cout &lt;&lt; &quot;The location of pass-by-value num is: &quot; &lt;&lt; &amp;num &lt;&lt; std::endl;
}

void foo1(int* num)
{
    std::cout &lt;&lt; &quot;The location of num* is: &quot; &lt;&lt; &amp;num &lt;&lt; &quot; But its value is :&quot; &lt;&lt; num &lt;&lt; std::endl;
}

void foo2(int&amp; num)
{
    std::cout &lt;&lt; &quot;The location of num&amp; is: &quot; &lt;&lt; &amp;num &lt;&lt; std::endl;
}

int main()
{
    int num;

    std::cout &lt;&lt; &quot;The location of num is: &quot; &lt;&lt; &amp;num &lt;&lt; std::endl;

    foo(num);
    foo1(&amp;num);
    foo2(num);
}

The output of this snippet is:

The location of num is: 0x7ffce8cceccc

The location of pass-by-value num is: 0x7ffce8ccecac

The location of num* is: 0x7ffce8cceca8 But its value is :0x7ffce8cceccc

The location of num&amp; is: 0x7ffce8cceccc

In foo we pass the value of the integer, therefore, we get a different address than the original.

In foo1, we pass the value of a pointer to num. The pointer has its own memory location, and its value is the memory address of num.

In foo2, we pass the reference to the integer num, and its memory address is exactly the memory address of the original, and this is a true pass-by-reference.

In order to edit such an object, you need to pass it by-pointer, or by-reference (generally, pass-by-reference is preferred over pointers whenever possible).

答案2

得分: 1

C++有按引用传递和按拷贝传递。
Java只有按拷贝传递(但是对象的内部对象指向与原始对象相同的引用)。

所以:

static void nullReference(int a []){ 
   a = null; // 对象的拷贝指向null
}

static void update(int a []) { 
 a[0]=5; // [0]来自原始引用。
}

public static void main (String args[]){ 
int a [] = {1,2,3}; 
nullReference(a); 
print(a == null); // false
update(a); 
print(a[0] == 5); // true
}
英文:

C++ has pass by reference and pass by copy.
Java has only pass by copy(But, the inner objects of the object point to the same reference as the original).

So:

static void nullReference(int a []){ 
   a = null; // the copy of the object points to null
}

static void update(int a []) { 
 a[0]=5; // [0] is from the original reference.

}

static void main (String args[]){ 
int a [] = {1,2,3}; 
nullReference(a); 
print(a == null); // false
update(a); 
print(a[0] == 5); // true

huangapple
  • 本文由 发表于 2020年3月17日 00:11:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/60709437.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定