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

发布于 2024-08-18 00:32:14 字数 1211 浏览 5 评论 0原文

我有一个函数,当尝试添加元素(如果数组已满)时,该函数会增长数组。哪个执行块更好或更快?

我认为我的第二个块(注释掉)可能是错误的,因为在将我的数组加倍后,我然后返回并指向原始块。

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

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

或者这仅仅意味着数组中元素的位置会被分割,从而导致性能不佳?

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
}

I have a function which grows an array when trying to add an element if it is full. Which of the execution blocks is better or faster?

I think my second block (commented out) may be wrong, because after doubling my array I then go back and point to the original.

When creating arrays does the compiler look for a contiguous block in memory which it entirely fits into? (On the stack/heap? I don't fully understand which, though it is important for me to learn it is irrelevant to the actual question.)

If so, would this mean using the second block could potentially overwrite other information by overwriting adjacent memory? (Since the original would use 20 adjacent blocks of memory, and the latter 40.)

Or would it just mean the location of elements in my array would be split, causing poor performance?

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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋叶绚丽 2024-08-25 00:32:14

第二个块根本无法实现你想要的。

当您这样做时

myStack = new int[length *= 2];

,系统将返回一个指针,指向分配新的更大数组的位置。

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

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

The second block wouldn't accomplish what you want at all.

When you do

myStack = new int[length *= 2];

then the system will return a pointer to wherever it happens to allocate the new, larger array.

You then reassign myStack to the old location (which you've already de-allocated!), which means you're pointing at memory that's not allocated (bad!) and you've lost the pointer to the new memory you just allocated (also bad!).

Edit: To clarify, your array will be allocated on the heap. Additionally, the (new) pointer returned by your larger array allocation (new int[foo]) will be a contiguous block of memory, like the old one, just probably in a different location. Unless you go out of bounds, don't worry about "overwriting" memory.

初吻给了烟 2024-08-25 00:32:14

由于以下顺序,您的第二个块不正确:

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,您必须执行创建新数组/复制/删除旧数组技术。

Your second block is incorrect because of this sequence:

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

tempStack and myStack and both simply pointers to the same block of memory. When you delete[] the pointer in the second line, you no longer have access to that memory via either pointer.

Using C++ memory management, if you want to grow an array, you need to create a new array before you delete the old one and copy over the values yourself.

That said, since you are working with POD, you could use C style memory management which supports directly growing an array via realloc. That can be a bit more efficient if the memory manager realizes it can grow the buffer without moving it (although if it can't grow the buffer in place, it will fall back on the way you grow your array in your first block).

C style memory management is only okay for arrays of POD. For non-POD, you must do the create new array/copy/delete old array technique.

我乃一代侩神 2024-08-25 00:32:14

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

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

反对 std::vector 的另一个论点是 std::vector 的怪异之处,但是如果您需要,您可以简单地使用 std::vectorstd::vector 代替。 (参见:http://www.gotw.ca/publications/mill09.htm

This doesn't exactly answer your question, but you shouldn't be doing either one. Generally new[] or delete[] should be avoided in favor of using std::vector. new[] is hard to use because it requires explicit memory management (if an exception is thrown as the elements are being copied, you will need to catch the exception and delete the array to avoid a memory leak). std::vector takes care of this for you, automatically grows itself, and is likely to have an efficient implementation tuned by the vendor.

One argument for using explicit arrays is to have a contiguous block of memory that can be passed to C functions, but that also can be done with std::vector for any non-pathological implementation (and the next version of the C++ standard will require all conforming implementations to support that). (For reference, see http://www.gotw.ca/publications/mill10.htm by Herb Sutter, former convener of the ISO C++ standards committee.)

Another argument against std::vector is the weirdness with std::vector<bool>, but if you need that you can simply use std::vector<char> or std::vector<int> instead. (See: http://www.gotw.ca/publications/mill09.htm)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文