0

Context: I need to move all elements from an array to a new array. The old array is to be destroyed after the copy.

Code:

int* array = new int[5];
int* newArray = new int[5];

Option 1: destroy elements in the loop

for (int i = 0; i < 5; ++i) {
  newArray[i] = array[i];
  delete (array + i);
}

Option 2: using delete[]

for (int i = 0; i < 5; ++i) {
  newArray[i] = array[i];
}
delete[] array;

Questions: What's the difference? Is delete[] more efficient than option1 (Does delete[] destroy a block of memory instead of erasing element by element? )?

lichgo
  • 523
  • 1
  • 6
  • 16

2 Answers2

3

Well, option 1 exhibits undefined behavior, so the difference is one of correct code and incorrect code.

You can only delete (or, in this case, delete[]) what was returned from new. The individual elements of the array were not returned by new (nor are they pointers). Calling delete on a pointer which was not returned by new, i.e., array + n invokes undefined behavior.

An implementation of new may allocate a bit more memory than was requested for bookkeeping. It gets a pointer, p, and then says "ok, now let's look at the info new created for me at p - sizeof(some_structure). Now I know that I allocated n bytes of memory because some_structure.n tells me so, so I'll clean that up now".

When it attempts to do that on the erroneous pointer you gave it it reads nonsense and anything can happen.


On a side note, prefer std::copy to copy an array, not a loop.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • Hi Ed. I got your point! Now I am curious about if " new int[3] " is equal to " new int(); new int(); new int(); " ? Are these dynamically created integers stored in heap memory instead of stack? – lichgo May 27 '14 at 02:36
  • @lichgo: The spec does not mention a "heap" or a "stack" as they are implementation details, but yes, in every implementation I know of it will be allocated on a heap structure dynamically (as opposed to variables with automatic storage duration which are located on the stack.) `new int()` returns a pointer to a single `int`, and you would free it with `delete p`. `new int[n]` returns a pointer to `n` `int`s and you delete it with `delete [] p`. The rule is; if you use `new []` then you free with `delete []`. Otherwise, you use `delete`, and you only ever `delete` what was returned by `new`. – Ed S. May 27 '14 at 02:39
  • @lichgo your premise is wrong. those things are not equivalent. Regardless, where the implementation stores the stuff is up to it; you're only concern as a language client is that it *can* (and does). – WhozCraig May 27 '14 at 02:40
  • "new and delete will almost certainly allocate a bit more" - this is often true of `new[]` as it needs to keep track of the number of elements so `delete[]` can iterate calling destructors, but for "plain" `new` many implementations will have a set of small fixed-sized areas (e.g. 8 byte capacity) and any pointer inside that area's size is implicitly known, and for other areas the size may be tracked outside the allocated area (e.g. in a distinct free list/tree). – Tony Delroy May 27 '14 at 02:51
1

delete and delete[] are fundamentally different (one cannot replace the other).

delete a deallocates the memory pointed to by a.

 a
 |
 v
 Abcde

delete[] deallocates the memory for the array starting at a.

 a
 |
 v
 AbcdeAbcdeAbcdeAbcde

The first is not for an array; the second is for an array.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285