为什么C ++和Java中的动态数组具有不同的初始容量?

时间:2017-08-08 20:33:29

标签: java c++ arrays stdvector cross-language

所以我一直在寻找动态数组的实际工作方式。我发现的是两个不同的概念。

在C ++中

在C ++中,动态数组通常由向量实现。向量将容量设置为0,增加计数以插入新元素,然后将新插入的容量大小加倍。

vector.h

/*
 * Implementation notes: Vector constructor and destructor
 * -------------------------------------------------------
 * The constructor allocates storage for the dynamic array and initializes
 * the other fields of the object.  The destructor frees the memory used
 * for the array.
 */

template <typename ValueType>
Vector<ValueType>::Vector() {
   count = capacity = 0;
   elements = NULL;
}

用于扩展矢量大小

/*
 * Implementation notes: expandCapacity
 * ------------------------------------
 * This function doubles the array capacity, copies the old elements into
 * the new array, and then frees the old one.
 */

template <typename ValueType>
void Vector<ValueType>::expandCapacity() {
   capacity = max(1, capacity * 2);
   ValueType *array = new ValueType[capacity];
   for (int i = 0; i < count; i++) {
      array[i] = elements[i];
   }
   if (elements != NULL) delete[] elements;
   elements = array;
}

在Java中

在java中,动态数组是使用arrayList实现的,它们将容量设置为10(基于JVM),一旦容量满,它们就会增加容量。 将容量设置为10的原因是您不必为每次新插入频繁初始化内存。一旦容量完全增加容量大小。

好奇心

为什么在vector.h中实现将默认值设置为0?将容量设置为某个较小的值(比方说10)而不是将其设置为0可以节省每次用户插入元素时初始化内存的开销。

由于它是一个动态数组,因此设置较小的矢量容量不会有害,因为动态数组的大小一般超过10个。

编辑:我的问题是为什么默认为0?默认情况下,它可以是任何小值,因为无论如何,矢量将扩展到某个特定大小,这是首先使用矢量的目的。

3 个答案:

答案 0 :(得分:6)

默认情况下,容量为零的优势在于默认构建std::vector根本不会进行任何动态内存分配(你不会为你所做的事付出代价)需要)。 如果您知道需要~10个元素,则可以通过调用std::vector::reserve明确设置容量:

std::vector<int> vec;
vec.reserve(10);

我只能推测,为什么Java做的事情有所不同,但afaik,动态内存分配在Java中比在c ++中更便宜,而且这两种语言在性能/低级控制与简单性方面也遵循不同的理念。 p>

答案 1 :(得分:3)

  

为什么默认为0?

实际上它默认不是0。也就是the C++ language standard does not define (AFAIK) what the initial capacity of a default-constructed vector should be

在实践中,大多数/所有实现都默认为0容量。我想说的原因在于C ++语言的一个设计原则是:

  

你不使用什么,你不付钱。

(见:B. Stroustrup:The Design and Evolution of C++。Addison Wesley,ISBN 0 - 201 - 43330 - 3,1994年3月)

这不仅仅是一个微不足道的重言式 - 它是设计考虑的倾向。

因此,在C ++中,我们宁愿不为没有插入任何元素的向量支付任何,然后通过初始“牺牲”来节省潜在的大小增加。

正如@yurikilocheck指出的那样,std::vector类确实为您提供了reserve()方法,因此您可以自己设置初始容量 - 并且由于默认构造函数不分配任何内容,你不会为两次分配支付“额外费用” - 只需一次。再次,您(基本上)支付最低可能的费用。

编辑:另一方面,std::vector在分配更多空间时会部分地突破这一原则,而不是在达到其容量时实际需要的空间。但至少这不是一个多余的分配电话。

答案 2 :(得分:3)

我使用了一个实现,它为每个向量保留了32个元素的默认值。它是原生的Sun C ++ STL实现。那是一场灾难。我有一个完全合理的程序,它的性质必须有几十万这些载体。它的内存不足。它应该运行得很好,因为在那些成千上万的元素中,只有很小的百分比使这些向量非空。

因此,根据个人经验,0是最佳默认矢量大小。