Java 或 C++ 中的动态分配
Dynamic allocation in java or c++
如果我在C++中有一个指针,假设int* array;
,我为数组分配内存
array=new int[10];
然后,我初始化数组的所有 10 个元素,使用 0,1,2,3...在那之后,我做array=new int[15];
最初的前 10 个值还会存在吗?我想不是,如果我错了,请纠正我。
在C语言中,有函数realloc
,它具有上述效果。C++或java中是否有等价物?如何在 C++ 或 Java 中动态扩展数组(不使用 Vector 类,并且每次都不在另一个容量翻倍的数组中复制数组(?
每当new int[X]
X
是整数时,无论是在 C++ 还是 Java 中,您都会获得对新分配数组的引用。
在 Java 中,数组会自动初始化,以便每个条目都有其默认值(0 表示基元数据类型,null 表示引用数据类型(。在C++中,数组没有初始化,你会得到垃圾。
如果您这样做:
array = new int[10];
array[0] = 0;
array[1] = 1;
// etc
array = new int[15];
第二次创建数组并在变量array
中放置对它的引用时,您只会丢失对第一个数组的引用。由于它是一个新数组,它将遵守新分配数组的语言规则:在 Java 中,数组现在将指向大小为 15 的数组,填充零;在C++中,数组将指向大小为 15 的充满垃圾的数组。
在 Java 中,丢失的数组最终将为您进行垃圾回收。在C++中,您刚刚创建了内存泄漏。
这两种语言都禁止您调整大小,或者像您所说的那样动态扩展数组。您可以创建一个新文件,将所有内容从旧文件复制到新文件,然后丢弃旧文件。他们可能会提供为您执行这些操作的方法,但您不会扩展现有数组,您只需创建一个新数组并将数据从旧数组复制到新数组。
在 Java 中没有 realloc(但它有 Arrays.copyOf
,其工作原理类似(,而在 C++(和 C(中,realloc
不会真正扩展数组;它将在其他地方分配更多内存,释放先前分配的内存,并返回新指针:您必须替换任何指向新地址的现有指针!
最后,对于动态调整自身大小的集合类,它们通常有一个内部数组,每当该数组已满时,该类都会在内部执行所有调整大小的操作:它分配一个新的,更大的,复制元素,然后丢弃旧的。由于数组完全封装在类中,因此您无需担心对旧数组的引用,如我上面所解释的那样。
在java中,内存管理由JVM控制。这就是爪哇的美妙之处。您可以使用 System.arraycopy(( 函数来制作数组的副本。如果您的目标是扩展阵列,只需提供一个更大的数组作为目标数组。
另一方面,您可以使用集合框架来动态扩展集合。
数组概念的核心,无论是在C++还是Java中,都是固定大小的集合。 在这个概念中,realloc
可能看起来像某种后门,但它仍然不承诺扩展给定的数组 - 它可以在其他位置创建数组,复制原始内容并释放原始内存。而且很可能会。
因此,如果您想要可变大小集合,请在 C++ 中使用 std::vector
,在 Java 中使用ArrayList
。或者,您可以自己编写此功能。但是恐怕您将不得不从自己的内存分配器开始,因为一旦分配了内存块,您就无法使标准内存分配器扩展。
最初的前 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]();
// ^^
在 Java 中,您无法动态扩展数组。有不同的数据结构,如ArrayList。
在 Java 中,在您的示例中,如果没有对大小为 10 的第一个数组的引用,则它将被 GarbageCollector 收集。
如何在 Java 中动态扩展数组(不使用 Vector 类,并且每次都不在另一个容量翻倍的数组中复制数组(?
在java.util.Arrays
,有很多方法可以使用。在您的情况下,您需要copyOf
接口文档
array = Arrays.copyOf(array, 15);
在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++ 中内置动态内存分配的对象,因此您不必自己手动操作。
如果你真的想看看它是如何完成的,你可以自己做处理内存分配的对象。
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
这可能是唯一的方法。当然,您可以使用realloc
或memcpy
来复制值,但它基于空指针,对于初学者来说通常更棘手。希望这有所帮助,不要忘记为这个东西创建一个类或结构,否则,它会变得一团糟。
编辑:忘了提了,我的回答只包括C++,没有JAVA。
是的,C++中有一个等价物,即标准C++。
std::vector<int> array(10);
然后
array.resize(15);
vector
完全按照您期望的方式管理其存储内存。该vector
旨在替换 C 重新分配的数组指针。要替换堆栈上的数组,您std::array
自 C++11 起。要替换堆栈上的 VLA,您将在 C++14 或 C++17 中std::dynarray
。
不要被引诱,realloc
偶尔会复制其数据。(当它找不到足够的空间来获取重新分配的缓冲区时(
大约相当于C++的realloc
,不,没有对应于new
renew
的方式,就像有一个对应于malloc
的realloc
一样。而且它不是语言中缺少的东西。它已在std::vector
类中得到解决。它自己管理它的内存,它是高效的,不,使用它并不是不纯粹的风格。这是C++拥有可以调整大小的数组的标准方法。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 在c++中使用动态分配的问题
- 使用递归模板动态分配的多维数组
- 对具有动态分配的内存和析构函数的类对象的引用
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 访问动态分配列表中的元素
- 为什么 std::equal_to会导致动态分配?
- 调用析构函数以释放动态分配的内存
- 动态分配Q_Property变量
- 在 C++ 中搜索动态分配的数组中的出现次数
- 动态分配的聊天数组打印缺失的数据和空
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 使用动态分配将 char* 复制到另一个字符**
- 使用指针在存在特征库的情况下动态分配 c++ 中的矩阵
- 二维阵列的动态分配
- 0xC0000005:访问冲突写入位置0xCDCDCDCD动态分配错误
- 在运行时为动态分配的内存输入值
- 释放动态分配的内存时是否需要执行此额外步骤
- 动态分配字符数组的内存