views:

589

answers:

5

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?

+3  A: 

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
+1 consider using vector
obelix
Works only for Plain Old Data types.
peterchen
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
+6  A: 

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(temp, temp + 5, p); // Suggested by comments from Nick and Bojan
delete [] p;
p = temp;
Kim Gräsman
this is fine for 'int' type but for user defined types, `memcpy/delete []` approach can cause problems.
Nick D
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
Thanks guys, I changed to std::copy.
Kim Gräsman
+3  A: 

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
A: 

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
that is basically reimplementing vector, isn't it?
Naveen
if you don't want the vector, this is what you might do. But then, if you implement vector, you don't ask this question.
Glenn
+1  A: 

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.)

Pavel Shved