19

Lets say, i have

int *p;
p = new int[5];
for(int i=0;i<5;i++)
   *(p+i)=i;

Now I want to add a 6th element to the array. How do I do it?

Jesse Beder
  • 33,081
  • 21
  • 109
  • 146
  • 1
    If you indent four spaces in the editor, your code will look like code – Jesse Beder Aug 29 '09 at 06:21
  • 3
    You don't. If you want this kind of functionality, you'd use `std::vector`. If you don't use `std::vector`, you ought to know quite a lot about C++ (since you ask this, you probably don't have enough yet) and you should have a very good reason. Depending on that reason, the answer might differ. – sbi Aug 29 '09 at 14:42

5 Answers5

34

You have to reallocate the array and copy the data:

int *p;
p = new int[5];
for(int i=0;i<5;i++)
   *(p+i)=i;

// realloc
int* temp = new int[6];
std::copy(p, p + 5, temp); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
Kim Gräsman
  • 7,438
  • 1
  • 28
  • 41
  • 2
    this is fine for 'int' type but for user defined types, `memcpy/delete []` approach can cause problems. – Nick Dandoulakis Aug 29 '09 at 06:49
  • 2
    You can use std::copy instead of memcpy - it will work for PODs as well as objects with user-defined assignment operator and it is likely that it is optimized to memcpy for integral types. The optimization, however, is a quality-of-implementation issue. – Bojan Resnik Aug 29 '09 at 09:12
  • 1
    Thanks guys, I changed to std::copy. – Kim Gräsman Aug 29 '09 at 09:22
  • 4
    This was fixed thanks to a rejected edit by anonymous user. Thanks for finding that bug! It snuck in when I changed from memcpy to std::copy without checking order of arguments. http://stackoverflow.com/review/suggested-edits/1775715 <-- this should have been accepted! – Kim Gräsman Mar 26 '13 at 10:35
  • Can you please explain the problems associated with memcpy. Is it just safety checks for length and memory access or are there actual underlying problems with memcpy? – Jeremy Trifilo Feb 01 '19 at 14:47
  • 2
    @JeremyTrifilo The issue was raised for user-defined types. If you have an array of objects with user-defined assignment operators (e.g. they need to free/allocate private memory), `memcpy` will break as it just blits the bytes rather than invoking assignment for every element. – Kim Gräsman Feb 02 '19 at 15:07
11

You cannot. You must use a dynamic container, such as an STL vector, for this. Or else you can make another array that is larger, and then copy the data from your first array into it.

The reason is that an array represents a contiguous region in memory. For your example above, let us say that p points to address 0x1000, and the the five ints correspond to twenty bytes, so the array ends at the boundary of 0x1014. The compiler is free to place other variables in the memory starting at 0x1014; for example, int i might occupy 0x1014..0x1018. If you then extended the array so that it occupied four more bytes, what would happen?

Crashworks
  • 40,496
  • 12
  • 101
  • 170
3

If you allocate the initial buffer using malloc you can use realloc to resize the buffer. You shouldn't use realloc to resize a new-ed buffer.

int * array = (int*)malloc(sizeof(int) * arrayLength);
array = (int*)realloc(array, sizeof(int) * newLength);

However, this is a C-ish way to do things. You should consider using vector.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 2
    Works only for Plain Old Data types. – peterchen Aug 29 '09 at 09:41
  • You should probably add that what vector does, if he wants to emulate that, is allocate a new, bigger array, and copy the elements to that. The OP is aware of vector, so presumably there's a reason for not using it (homework, perhaps) – jalf Aug 29 '09 at 13:37
2

Same as others are saying, but if you're resizing the array often, one strategy is to resize the array each time by doubling the size. There's an expense to constantly creating new and destroying old, so the doubling theory tries to mitigate this problem by ensuring that there's sufficient room for future elements as well.

Glenn
  • 5,334
  • 4
  • 28
  • 31
2

Why don't you look in the sources how vector does that? You can see the implementation of this mechanism right in the folder your C++ include files reside!

Here's what it does on gcc 4.3.2:

  1. Allocate a new contiguous chunk of memory with use of the vector's allocator (you remember that vector is vector<Type, Allocator = new_allocator>?). The default allocator calls operator new() (not just new!) to allocate this chunk, letting himself thereby not to mess with new[]/delete[] stuff;

  2. Copy the contents of the existing array to the newly allocated one;

  3. Dispose previously aligned chunk with the allocator; the default one uses operator delete().

(Note, that if you're going to write your own vector, your size should increase "M times", not "by fixed amount". This will let you achieve amortized constant time. For example, if, upon each excession of the size limit, your vector grows twice, each element will be copied on average once.)

P Shved
  • 96,026
  • 17
  • 121
  • 165