gregghz
gregghz

Reputation: 3965

Expanding array capacity

I was thinking of ways to make an array larger quickly in C++ and I came up with this:

// set up arr1
int *arr1 = new int[5];

// add data to arr1
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
arr1[3] = 4;
arr1[4] = 5;

// set up arr2
int *arr2 = new int[10];
arr2 = arr1; // assign arr1 to arr2

// add more values
arr2[5] = 6;
arr2[6] = 7;
arr2[7] = 8;
arr2[8] = 9;
arr2[9] = 10;

Is this even safe? I worry that this will cause some strange behavior and that arr2 is just an int[5] array and you're now overwriting data that doesn't belong to it.

Upvotes: 2

Views: 1440

Answers (7)

Nim
Nim

Reputation: 33655

NO.

arr2 = arr1;

Does not do what you think it does!

There is already something in the STL for this, it's called vector.


For the sake of completeness.. :)

arr2 before the assignment held the address if the start of the array of 10 items you allocated. After the assignment, rather than copying the contents the block addressed by arr1 (which I guess is what you wanted to do), the assignment merely changes the address that arr2 holds to the address that arr1 holds (i.e. start of the 5 item array), for the rest of your code, this has two consequences:

  1. You no longer have the address of the block of 10 items you allocated, so you have no way of releasing that block - hence you have a memory leak (should your program continue to operate)
  2. Though you initially allocated 10 items for arr2, by the assignment, you're now addressing a block that only has 5 items, and accessing anything outside of that block of 5 (i.e. indexes 5 onwards) is likely to end in nasal daemons paying a visit with a very large cricket bat - or you may get lucky...

So what can you do:

  1. Use std::vector<int>, one if it's design features is to take this kind of burden away from you (unless you're interested in implementing another container), if that's the case
  2. Use a copy operation to correctly copy the contents rather than assign the addresses, as suggested, use std::copy - or others, such as memcpy (prefer memmove - it's a little slower but is well defined for overlapping blocks etc.)

Upvotes: 8

ActiveX
ActiveX

Reputation: 1166

Just to add to the other comments which are correct. The reason why you will leak memory is that you have replaced arr2 pointer that pointed to allocated memory for arr2 with arr1 pointer. Now arr1, arr2 point to the same thing, the array of 5 elements. When you try to clean up with delete operator, you can only clean up the 5 element array since the pointer to 10 element array has been overriden.

Upvotes: 2

Mahesh
Mahesh

Reputation: 34625

Is this even safe?

No

arr2 = arr1; // assign arr1 to arr2

arr2 is also pointing to first index element of arr1. And by doing it, arr2 looses the location where it was earlier pointing to returned by new. So, there is memory leak.

Use std::vector instead to expand the array.

Upvotes: 2

Cubbi
Cubbi

Reputation: 47428

The line arr2 = arr1; leaks memory, and all the following arr2[...]= lines invoke undefined behavior as they access the array of 5 ints outside of its bounds.

To do what you wanted to do, replace arr2 = arr1; with std::copy(arr1, arr1+5, arr2); (example program: https://ideone.com/3Rohu)

To do this properly, use std::vector<int>

Upvotes: 6

Gareth McCaughan
Gareth McCaughan

Reputation: 19971

No, it's not safe at all. When you said arr2=arr1; you didn't copy any of the data across, you just reassigned a pointer. Now the memory you allocated with int *arr2 = new int[10]; has been leaked, and arr2 points to the original 5-element array, and when you start saying things like arr2[5] = 6; you are writing beyond the end of that array and all hell may break loose.

Upvotes: 3

Jesus Ramos
Jesus Ramos

Reputation: 23268

It's not safe that's actually a memory leak. You're not doing anything with arr2 you just ended up setting arr2 to the address of r1, remember in c and c++ theres no bounds checking so you're overwriting another stackframe by doing that

Upvotes: 2

Bj&#246;rn Pollex
Bj&#246;rn Pollex

Reputation: 76788

This leaks memory, because you are assigning pointers.

int *arr2 = new int[10];
arr2 = arr1; // this does not assign the values

The second assignment makes arr2 point to the array arr1. You loose the array you have previously allocated, and can never delete it.

To avoid this, use an std::vector.

Upvotes: 5

Related Questions