1

I have an array of integers that I pass into function. Then I want to make a dynamic array in that function as a copy of the first array, but whenever I change the value of an element in second array (copy), the value in the first array also changes. What am I doing wrong?

example:

int *array1 = new int[N]
int *array2 = new int[N]
array2 = array1;

array2[1]=2; //element of the first array at index 1 also becomes 2

Thank you.

Luki
  • 409
  • 11
  • 25
  • 6
    What you really want is `std::vector`. `array2 = array1;` is a memory leak. – NathanOliver Feb 23 '17 at 12:59
  • I would understand the downvote, if there was a good dupe, but to my surprise I could not fine one – 463035818_is_not_an_ai Feb 23 '17 at 13:03
  • 1
    found one that is close enough. It has quite exhaustive answer. Look for "assignment" in one of the answers – 463035818_is_not_an_ai Feb 23 '17 at 13:06
  • You are reassigning the pointer of array2 to the one in array1, aka both pointers point at the same object in the heap (and you lost any pointers to the actual element of array2 in the heap, thus a memory leak). If you want an *object copy*, something like *array2 = *array1 (i.e. dereferencing the pointers before assignment) could work, but this is just a guess, since I haven't worked much with dynamic arrays. – kushy Feb 23 '17 at 13:08
  • 1
    ..and even if you found the answer to your problem, you should consider using `std::vector` or `std::array` instead, because they eliminate such problems – 463035818_is_not_an_ai Feb 23 '17 at 13:08
  • @kushy `*array2 = *array1` is wrong – 463035818_is_not_an_ai Feb 23 '17 at 13:10
  • @tobi303 Ok, I see. Apparently even non-pointer array assignments don't cover all elements of the array. Guess `std::vector` or `std::array` is really the way to go here. – kushy Feb 23 '17 at 13:12
  • 1
    @kushy To make it precise for you: *array1 is the first element of that array. some_array[5] = 4; does the same as *(some_array + 5) = 4;. The brackets are essentially a convenient way to express such a statement. You might want to read an article about pointer arithmetics, good to know even though there is not much reason to use raw pointers over something like vector. – Aziuth Feb 23 '17 at 13:41

4 Answers4

4

The Explanation:

Since we are dealing with C++, there is pretty much no reason to use new int[N] instead of std::vecotr<int> of a size N.

To explain what is happening in your code: You create a pointer named array1 and allocate memory enough to contain N integers. You do the same with second pointer, called array2. Since the names array1 and array2 are just pointers to memory, what they point to can be changed. In the line array2 = array1 you change to what is pointing array2 to memory allocated and pointed to by array1 pointer.

So what happens now? Really bad stuff. You are encountering a memory leak. The memory that was pointed to by array2 is still there, still allocated, but you are unable to access it, since your only access to it (array2 pointer) now points to entirely different part of memory. You now also have 2 pointers that point to the same memory (originally the memory that was allocated in the line int *array1 = new int[N]).

How to improve your code?

Use std::vector<int>. Vector class comes with well written and safe assignment operator that will work for you here:

std::vector<int> array1(N);
std::vector<int> array2(N);

array2 = array1;

Now you have 2 identical vectors, memory is managed well (array1 and array2 are separate entities. They do not share the same memory and can be freely changed without affecting the other one) and your code looks pretty.

What if you cannot change everything to std::vector?

You mentioned having an array that you pass into a function. Let's call it an original_array of a size N. Consider this code, which uses similar signature, but uses safe memory management by converting array to vector:

void copy_and_do_stuff(int original_array[], int N)
{
    std::vector<int> array2;
    std::copy(original_array, original_array + N, array2.begin());

    // here, the vector "array2" is a copy of your `original_array`. Changes
    // to it will not affect your argument.

    // ... do whatever you need to do in this function ...
}

Remember to add #include <vector> and #include <algorithm> to use vectors and std::copy function.

Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • you can also use the constructor that takes two iterators instead of copying. Something like `std::vector array2(*(original_array[0]),*(original_array[0])+N)` – 463035818_is_not_an_ai Feb 23 '17 at 13:57
  • 1
    @Dan Wouldn't necessarily call it a bad question. I mean, it's a beginner who doesn't know something, why not help him? I doubt that he would have found something using a search engine. Also, your link says "save yourself some frustration", so it's more like a sound advice in regard to confused questions. – Aziuth Feb 23 '17 at 13:57
  • @Dan I would understand the possible downvote and I appreciate your comment – Fureeish Feb 23 '17 at 13:58
  • @Aziuth true. I had to to search quite a bit to find a dupe – 463035818_is_not_an_ai Feb 23 '17 at 13:59
1

To give a full answer, although the comments say everything important so far:

The line array2 = array1; does the following: take the address that is stored in array1 and store it also in array2. They are both pointing at the same location now (and the old, reserved storage is still reserved but not pointed at, aka a memory loss)

In any case, pointers are somewhat dangerous things, easily leading to unexpected behaviour, especially if you are a beginner. Therefore, you want to use std::vector:

//at the head of the file
#include <vector>
using std::vector;

//in the program
vector<int> array_1(n);

//do something with array_1:
array_1[0] = 1;
array_1[1] = ...

vector<int> array_2 = array_1; //actually copies the content

or:

vector<int> array_2(array_1); //copy constructor

At some point you will want to investigate how vector works internally (it wraps an array, actually), but for now, simply use vector. Read it's documentation. You can do all sorts of things on it with the STD library, like for example having it sorted by std::sort.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Aziuth
  • 3,652
  • 3
  • 18
  • 36
-1

As mentioned in the comments you probably shouldn't be doing this in c++; std::vector is THE optimized; safe and reliable way to handle data of this sort.

But it is clear from your question that you don't really understand pointers.

This is what you code does:

int *array1 = new int[N]; //allocate memory for the first array
int *array2 = new int[N]; //allocate memory for the second array
array2 = array1; //OVERWRITE the location of the second array 
                 //with that of the first (thus destroying your 
                 //only pointer to the second array and creating a 
                 //memory leak)

To achieve what you want in array2=array1 you need to write a loop and copy every integer ELEMENT of the array across to the new array - this creates a 'deep' copy.

Elemental
  • 7,365
  • 2
  • 28
  • 33
-2

array1 and 2 are pointers in your case. When you do:

array2 = array1;

array2 points to the same memory location as array1, and the old array2 is lost in memory (and so it creates a memory leak, as Elemental said) You need to copy the array elements by hand or use std::vector

Dragos Pop
  • 428
  • 2
  • 8