1

如果我在 C++ 中有一个指针,比方说int* array;,我为数组分配内存

array=new int[10];

然后,我用 0、1、2、3 初始化数组的所有 10 个元素......之后,我array=new int[15]; 会做最初的前 10 个值仍然存在吗?我认为不是,如果我错了,请纠正我。

在 C 中有函数realloc,它具有上述效果。C++ 或 java 中是否有任何等价物?如何在 C++ 或 Java 中动态扩展数组(不使用 Vector 类,并且不每次都将数组复制到另一个具有双倍容量的数组中)?

4

9 回答 9

3

每当您在 C++ 和 Java 中执行new int[X]where Xis an integer 时,您都会获得对新分配数组的引用。

在 Java 中,数组会自动初始化,因此每个条目都有其默认值(原始数据类型为 0,引用数据类型为 null)。在 C++ 中,数组没有初始化,你会得到垃圾。

如果你这样做:

array = new int[10];
array[0] = 0;
array[1] = 1;
// etc
array = new int[15];

第二次创建数组并将对它的引用放入变量array中时,您只会丢失对第一个数组的引用。由于它是一个数组,它将遵守语言新分配数组的规则:在 Java 中,数组现在将指向一个大小为 15 且填充了零的数组;在 C++ 中,array 将指向一个大小为 15 的充满垃圾的数组。

在 Java 中,丢失的数组最终会被垃圾回收。在 C++ 中,您刚刚创建了内存泄漏。

两种语言都禁止您调整数组的大小,或者如您所说,动态扩展数组。您可以创建一个新的,将旧的所有内容复制到新的,然后丢弃旧的。他们可能会提供为您执行这些操作的方法,但您不会扩展现有数组,您只需创建一个新数组并将数据从旧数组复制到新数组。

在 Java 中没有realloc(但它有Arrays.copyOf,它的工作方式类似),而在 C++(和 C 也是)中,realloc不会真正扩展数组;它将在别处分配更多内存,释放先前分配的内存,并返回新指针:您必须替换任何指向新地址的现有指针!

最后,对于动态调整自身大小的集合类,它们通常有一个内部数组,并且当该数组变满时,该类会在内部完成所有调整大小的工作:它分配一个更大的新数组,复制元素,并丢弃旧数组。由于数组完全封装在类中,因此您无需担心对旧数组的引用,正如我上面解释的那样。

于 2013-06-26T14:03:24.547 回答
2

在 C++ 和 Java 中,数组概念的核心是固定大小的集合。realloc在这个概念中可能看起来像某种后门,但它仍然不承诺扩展给定数组 - 它可能会在其他位置创建数组,复制原始内容并释放原始内存。而且很可能会。
因此,如果您想要可变大小的集合,请std::vector在 C++ 和ArrayListJava 中使用。或者您可以自己编写此功能。但是恐怕您必须从自己的内存分配器开始,因为一旦分配了一块内存,您就无法使标准的内存分配器扩展。

于 2013-06-26T14:20:09.650 回答
1

最初的前 10 个值还会存在吗?

在 C++ 中,会有某个地方,但你已经失去了对它们的控制。他们将无法访问。这构成了内存泄漏。

int* array=new int[10]; // array points to dynamically allocated array
array=new int[15]; // array points to a completely different place now

在上面的示例中,array指针是您在第一个动态分配的数组上拥有的唯一句柄。通过将其指向其他地方,您会泄漏数组。

另请注意,在 C++ 中,数组的元素不是零初始化的。为此,您需要对数组进行值初始化:

int* array=new int[10]();
//                    ^^
于 2013-06-26T14:02:07.220 回答
1

在 Java 中,内存管理由 JVM 控制。这就是java的美妙之处。您可以使用 System.arraycopy() 函数来制作数组的副本。如果您的目标是扩展数组,只需提供一个更大的数组作为目标数组。

另一方面,您可以使用集合框架来动态扩展集合。

于 2013-06-26T14:04:46.377 回答
0

在 Java 中,您不能动态扩展数组。有不同的数据结构,比如 ArrayList。

在 Java 中,在您的示例中,如果没有对大小为 10 的第一个数组的引用,它将由 GarbageCollector 收集。

于 2013-06-26T14:01:38.650 回答
0

在 C++ 中,new 总是返回一个指针。数组的名称是指向数组中第一个元素的指针,所以这就是会发生的情况。

 int *array;           //get a point of type int
 array=new int[10];    //allocate 10 ints, and set the array ponter to the first one

 array = new int[15]   //allocate 15 ints, and set the array pointer to the first one

问题是现在我们无法知道前 10 个整数在内存中的位置。操作系统“认为”我们正在使用它 b/c 我们要求它。但我们不能使用它 b/c 我们不知道它在哪里。


现在有一些有用的东西。使用向量,向量是 c++ 中内置的动态内存分配的对象,因此您不必自己手动进行。

如果您真的想看看它是如何完成的,您可以自己制作处理内存分配的对象。

于 2013-06-26T14:06:54.020 回答
0

如何在 Java 中动态扩展数组(不使用 Vector 类,并且不每次都将数组复制到另一个具有双倍容量的数组中)?

java.util.Arrays,有很多方法可以使用。在您的情况下,您需要copyOf

API 文档

array = Arrays.copyOf(array, 15);
于 2013-06-26T14:08:27.937 回答
0

是的,C++ 中有一个等价物,即标准 C++。

std::vector<int> array(10);

接着

array.resize(15);

vector完全按照您期望的方式管理其存储内存。vector旨在替换 C 的重新分配的数组指针。要替换堆栈上的数组,您std::array从 C++11 开始就有了。要替换堆栈上的 VLA,您将使用std::dynarrayC++14 或 C++17。

不要被引诱,realloc偶尔复制它的数据。(当它没有找到足够的空间来获得重新分配的缓冲区时)

大约相当于reallocfor C++,不,没有renew对应new的方式有realloc对应的malloc。这不是语言中缺少的东西。它已在std::vector课堂上解决。它自己管理它的内存,它是高效的,不,使用它并不是不纯粹的风格。拥有可以调整大小的数组是 C++ 中的标准方法。

于 2013-06-26T14:13:25.093 回答
0

C++ 中最好的选择是 stl,std::vector<int>我不知道你为什么不能使用它,但可以说,你不能。可能是最好的方法:

const int c_startSize = 10;
const int c_increasing = 13;   //1.3

int * array;
int arraySize = c_startSize;
array = new int[arraySize];
//some code
//now we need to increase size of array.
int * tmp;
tmp = new int[arraySize * c_increasing / 10];
for (int i = 0; i < arraySize; i++)
    tmp[i] = array[i];
arraySize = arraySize * c_increasing / 10;
delete [] array;
array = tmp;
//some code

这可能是唯一的方法。当然你可以使用reallocormemcpy来复制值,但它基于 void 指针,对于初学者来说通常比​​较棘手。希望这会有所帮助,不要忘记为这个东西创建一个类或一个结构,否则,它将变得一团糟。

编辑:忘了提,我的答案只包括 C++,不包括 JAVA。

于 2013-06-26T14:15:02.003 回答