Copying from One Dynamically Allocated Array to Another C++
Asked Answered
J

4

9

This seems like it should have a super easy solution, but I just can't figure it out. I am simply creating a resized array and trying to copy all the original values over, and then finally deleting the old array to free the memory.

void ResizeArray(int *orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = orig[i];
    delete [] orig;
    orig = resized;
}

What seems to be happening here is that resized[i] = orig[i] is copying values by reference rather than value, as printing orig after it gets resized returns a bunch of junk values unless I comment out delete [] orig. How can I make a deep copy from orig to resized, or is there some other problem that I am facing? I do not want to use std::vector.

Jackal answered 8/11, 2011 at 20:34 Comment(3)
Note that there is no such thing as "copying values by reference". Either you're creating a new reference to the same data or your are copying.Towland
Even if you don't want to use std::vector, you would gain a lot by wrapping this in a class so that clients can pass around an invariant object and not have to manage the fact that the implementation pointer is changing with every resize. :-/Mabuse
As an optimization, you could copy the array contents with memcpy. I checked with godbolt and neither gcc nor clang replace the copy loop with memcpy (I thought they do that sometimes these days, but not here).Livy
P
15

Remember, parameters in C++ are passed by value. You are assigning resized to a copy of the pointer that was passed to you, the pointer outside the function remains the same.

You should either use a double indirection (or a "double pointer", i.e. a pointer to a pointer to int):

void ResizeArray(int **orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = (*orig)[i];
    delete [] *orig;
    *orig = resized;
}

or a reference to the pointer:

void ResizeArray(int *&orig, int size) {
    int *resized = new int[size * 2]; 
    for (int i = 0; i < size; i ++)
        resized[i] = orig[i];
    delete [] orig;
    orig = resized;
}

By the way, for array sizes you should use the type std::size_t from <cstddef> - it is guaranteed to hold the size for any object and makes clear that we are dealing with the size of an object.

Primero answered 8/11, 2011 at 20:38 Comment(3)
+1 The other option is to return the new array using... the return value.Towland
@AndréCaron: that's an option too, but I think that these forms suit better the indented use.Primero
As a point of clarification, by "double pointer" the respondent means "double indirection". When I first read it, I was confused why he wanted to substitute double * for int *.Ascarid
K
2

orig must be a pointer to a pointer to assign it to resized:

int **orig;
*orig = resized;
Kwan answered 8/11, 2011 at 20:40 Comment(0)
F
2

I highly suggest replacing the arrays with std::vector<int>. This data structure will resize as needed and the resizing has already been tested.

Frisco answered 8/11, 2011 at 20:41 Comment(2)
While vectors in general are something interesting, there also exist a variety of reason against them. Thus, your answer is opinion-based and rather a comment than an actual answer to OP's problem.Flywheel
@Markus: One could say the same about arrays. There also exists a variety of reasons against them, thus the OP's issue is opinion based and should be closed (and maybe deleted).Frisco
W
0

I'm copying a dynamic array.

    #include <iostream>

    void FillArray(int* const arr, const int size)
    {
       for(int i = 0; i < size; i++)
       {
           arr[i] = rand() % 10;
       }
    }

    void ShowArray(int* const arr, const int size)
    {
        for(int i = 0; i < size; i++)
        {
            std::cout << arr[i] << '\t';
        }
        std::cout << std::endl;
    }

    int main()
    {
        int size = 10;
        int *arr1 = new int [size];
        int *arr2 = new int [size];

        FillArray(arr1, size);
        FillArray(arr2, size);

        std::cout << "arr1 = ";
        ShowArray(arr1, size);
        std::cout << "arr2 = ";
        ShowArray(arr2, size);

        delete [] arr1;
        arr1 = new int [size];
        for(int i = 0; i < size; i++)
        {
            arr1[i] = arr2[i];
        }

        std::cout << "==========================" << std::endl;

        std::cout << "arr1 = ";
        ShowArray(arr1, size);
        std::cout << "arr2 = ";
        ShowArray(arr2, size);

        delete [] arr1;
        delete [] arr2;
    }
Willena answered 1/10, 2023 at 12:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.