gpt4 book ai didi

java - C++ 和 Java 数组声明/定义 : differences

转载 作者:可可西里 更新时间:2023-11-01 16:01:20 27 4
gpt4 key购买 nike

我的问题真的很简单(这并不意味着答案会很简单..:D)

为什么 C++ 中的数组将大小作为类型的一部分,而 Java 中却没有?

我知道 Java 数组引用变量只是指向堆上数组的指针,但 C++ 指向数组的指针也是如此,但即使那样我也需要提供一个大小。先分析一下C++:

// in C++ :

// an array on the stack:
int array[*constexpr*];

// a bidimensional array on the stack:
int m_array[*constexpr1*][*constexpr2*];

// a multidimensional array on the stack:
int mm_array[*constexpr1*][*constexpr2*][*constexpr3*];

// a dynamic "array" on the heap:
int *array = new int[n];

// a dynamic bidimensional "array" on the heap:
int (*m_array)[*constexpr*] = new int[n][*constexpr*];

// a dynamic multidimensional "array" on the heap:
int (*mm_array)[*constexpr*][*constexpr*] = new int [n][*constexpr1*][*constexpr2*];

n 不必是编译时常量表达式,所有元素都默认初始化。动态分配的“数组”不是数组类型,但新表达式产生指向第一个元素的指针。

所以当我创建一个动态数组时,除了第一个维度之外的所有维度都必须是常量表达式(否则我无法声明指针来保存它们的元素)。对不对??

现在转到 Java。我只能在堆上分配数组,因为这是 Java 的工作方式:

// a dynamic array on the heap:
int[] array = new int[n];

// a dynamic bidimensional array on the heap:
int[][] m_array = new int[n][];

// a dynamic multidimensional array on the heap:
int[][][] mm_array = new int [n][][];

在Java中,定义数组引用变量时似乎并不关心数组大小(在Java中显式提供大小是错误的),所以我只需要在创建时提供第一个维度的大小阵列。这允许我创建锯齿状数组,我不确定我是否可以在 C++ 中创建它(不是指针数组)。

谁能给我解释一下这是怎么回事?也许幕后发生的事情应该清楚。谢谢。

最佳答案

那是因为在 Java 中,所有数组都是一维的。 Java 中的二维数组仅仅是对一维数组的引用的数组。 Java 中的三维数组只是对数组的引用的一维数组,对数组的引用是对您想要的任何基本类型的数组的引用。

或者在 C++ 中,Java 中的数组,如果它不是原始数组,它就是“指针数组”。

例如,这段代码:

    int[][][] arr3D = new int [5][][];

System.out.println(Arrays.deepToString(arr3D));

将产生输出:

[null, null, null, null, null]

You can decide to initialize one of its elements:

    arr3D[2] = new int[3][];

来自同一个 println 的输出现在是:

[null, null, [null, null, null], null, null]

Still no ints here... Now we can add:

    arr3D[2][2] = new int[7];

现在的结果是:

[null, null, [null, null, [0, 0, 0, 0, 0, 0, 0]], null, null]

So, you can see that this is an "array of pointers".

In C++, when you allocate a multi-dimensional array the way you described, you are allocating a contiguous array which actually holds all the dimensions of the array and is initialized all the way through to the ints. To be able to know whether it's a 10x10x10 array or a 100x10 array, you have to mention the sizes.

Further explanation

In C++, the declaration

int (*mm_array)[5][3];

表示“mm_array 是一个指向 5x3 整数数组的指针”。当您向它分配某些内容时,您希望该内容是指向连续内存块的指针,该内存块至少大到足以包含 15 个整数,或者可能是多个此类 5x3 数组的数组。

假设您没有提到“5”和“3”。

int (*mm_array)[][]; // This is not a legal declaration in C++

现在,假设你得到了一个指向新分配的数组的指针,我们有如下语句:

mm_array[1][1][1] = 2;

或者

mm_array++;

为了知道把数字放在哪里,它需要知道数组的索引 1 在哪里。元素 0 很简单 - 它就在指针处。但是元素 1 在哪里?之后应该是 15 个整数。但是在编译时,你不会知道,因为你没有给出大小。 ++ 也是如此。如果它不知道数组的每个元素都是 15 个整数,它如何跳过那么多字节?

再者,什么时候是3x5或者5x3的数组呢?如果它需要转到元素 mm_array[0][2][1],它需要跳过两行五个元素,还是两行三个元素?

这就是为什么它需要在编译时知道其基本数组的大小。由于指针中没有关于大小的信息,而只是指向一个连续的整数 block ,因此需要提前知道该信息。

在 Java 中,情况有所不同。数组本身及其子数组都是 Java 对象。每个数组都是一维的。当你有这样的表达时

arr3D[0][1][2]

arr3D 已知是对数组的引用。该数组具有长度和类型信息,以及一维引用。它可以检查 0 是否为有效索引,并取消引用第 0 元素,该元素本身是对数组的引用。

这意味着现在它再次具有类型和长度信息,然后是引用的单一维度。它可以检查 1 是否是该数组中的有效索引。如果是,它可以转到该元素,取消引用它,并获取最里面的数组。

由于数组不是连续的 block ,而是对对象的引用,因此您不需要在编译时知道大小。一切都是动态分配的,只有第三层(在本例中)有实际连续的整数——只有一个维度,不需要预先计算。

关于java - C++ 和 Java 数组声明/定义 : differences,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32767077/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com