How to expand an array dynamically in C++? {like in vector }

75,696

Solution 1

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;

Solution 2

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?

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

Solution 4

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

Solution 5

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.

Share:
75,696
Jesse Beder
Author by

Jesse Beder

Googler, mathematician. Check out Optia, a puzzle game for iOS, or yaml-cpp, a YAML parser/emitter library in C++.

Updated on December 09, 2020

Comments

  • Jesse Beder
    Jesse Beder over 3 years

    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
      Jesse Beder almost 15 years
      If you indent four spaces in the editor, your code will look like code
    • sbi
      sbi almost 15 years
      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.
  • Kiran Kumar
    Kiran Kumar almost 15 years
    that is basically reimplementing vector, isn't it?
  • Nick Dandoulakis
    Nick Dandoulakis almost 15 years
    this is fine for 'int' type but for user defined types, memcpy/delete [] approach can cause problems.
  • Bojan Resnik
    Bojan Resnik almost 15 years
    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.
  • Kim Gräsman
    Kim Gräsman almost 15 years
    Thanks guys, I changed to std::copy.
  • peterchen
    peterchen almost 15 years
    Works only for Plain Old Data types.
  • josesuero
    josesuero almost 15 years
    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)
  • Glenn
    Glenn almost 15 years
    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.
  • Kim Gräsman
    Kim Gräsman over 11 years
    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. stackoverflow.com/review/suggested-edits/1775715 <-- this should have been accepted!
  • Jeremy Trifilo
    Jeremy Trifilo over 5 years
    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?
  • Kim Gräsman
    Kim Gräsman over 5 years
    @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.