调整数组大小 - 两个执行块之间的差异?

时间:2010-01-15 19:23:50

标签: c++ arrays resize

我有一个函数,在尝试添加一个元素时会生成一个数组。哪个执行块更好或更快?

我认为我的第二个区块(已注释掉)可能是错误的,因为在我的阵列加倍之后我会回去指向原始区域。

在创建数组时,编译器是否在内存中寻找一个完全适合的连续块?(在堆栈/堆上?我不完全理解哪个,尽管对我来说很重要学习它与实际问题无关。)

如果是这样,这是否意味着使用第二个块可能会通过覆盖相邻的内存来覆盖其他信息?(因为原始版本将使用20个相邻的内存块,后者将使用20个。)

或者它只是意味着我的数组中元素的位置会被拆分,导致性能不佳?

void Grow()
{
  length *= 2; // double the size of our stack

  // create temp pointer to this double sized array
  int* tempStack = new int[length];

  // loop the same number of times as original size
  for(int i = 0; i < (length / 2); i++) 
  {
    // copy the elements from the original array to the temp one
    tempStack[i] = myStack[i]; 
  }

  delete[] myStack; //delete the original pointer and free the memory
  myStack = tempStack; //make the original point to the new stack

  //Could do the following - but may not get contiguous memory block, causing
  // overwritten >data
#if 0
  int* tempStack = myStack; //create temp pointer to our current stack
  delete[] myStack; //delete the original pointer and free memory
  myStack = new int[length *= 2]; //delete not required due to new?
  myStack = tempStack;
#endif
}

3 个答案:

答案 0 :(得分:2)

第二个区块根本无法达到你想要的效果。

当你这样做时

myStack = new int[length *= 2];

然后系统将返回一个指针,指向分配新的更大数组的地方。

然后你将myStack重新分配到旧位置(你已经取消分配了!),这意味着你指的是没有分配的内存(坏!)并且你丢失了指向新内存的指针你刚刚分配(也很糟糕!)。

编辑:为了澄清,您的阵列将在上分配。此外,较大的数组分配(new int[foo])返回的(新)指针将是一个连续的内存块,就像旧的一样,可能位于不同的位置。除非你走出界限,否则不要担心“覆盖”记忆。

答案 1 :(得分:1)

由于此序列,您的第二个块不正确:

int* tempStack = myStack; //create temp pointer to our current stack
delete[] myStack; //delete the original pointer and free memory

tempStack和myStack都只是指向同一块内存的指针。当您删除第二行中的[]指针时,您无法再通过任一指针访问该内存。

使用C ++内存管理,如果要增长数组,则需要先创建一个新数组,然后再删除旧数组并自行复制数值。

也就是说,既然你正在使用POD,你可以使用C风格的内存管理,它支持通过realloc直接增长数组。如果内存管理器意识到它可以在不移动缓冲区的情况下增加缓冲区,那么这可能会更高效一些(尽管如果它不能增加缓冲区,它将会回退到你在第一个块中增长数组的方式)。

C风格的内存管理仅适用于POD阵列。对于非POD,您必须创建新的数组/复制/删除旧数组技术。

答案 2 :(得分:1)

这并不能完全回答你的问题,但你不应该做任何一个问题。通常应避免new[]delete[]使用std::vectornew[]很难使用,因为它需要显式的内存管理(如果在复制元素时抛出异常,则需要捕获异常并删除数组以避免内存泄漏)。 std::vector会为您处理此问题,自动增长,并且可能会有一个由供应商调整的有效实施。

使用显式数组的一个参数是拥有一个可以传递给C函数的连续内存块,但对于任何非病态实现(以及下一个版本的实现),也可以使用std::vector来完成。 C ++标准将要求所有符合要求的实现都支持)。 (供参考,请参阅ISO C ++标准委员会前召集人Herb Sutter的http://www.gotw.ca/publications/mill10.htm。)

针对std::vector的另一个论点是std::vector<bool>的奇怪之处,但如果您需要,可以简单地使用std::vector<char>std::vector<int>。 (见:http://www.gotw.ca/publications/mill09.htm