Errors with dynamic Array created with new after passed to resize function

1

I am trying to implement a dynamically created array using new that I want to resize but the resize action is not working correctly.

This is an exercise on dynamic arrays, so I need dynamic arrays using new and not std::vector.

Here is my code :

int main ()
{
    // Build an application here
    int length = 0;
    int size = 0;
    int input;
    bool endAdding = false;

    cout << "Please enter the length of the new array : ";
    cin >> length;

    int* oPtrDynamicArray = CreateDynamicArray (length, size);

    do
    {
        cout << "Add an element (0 to quit) : " << endl;
        cin >> input;
        cout << endl << endl;

        if (input == 0){
            endAdding = true;
        }
        else
        {
            InsertElement(oPtrDynamicArray, input, size, length);
        }
        cout << "The array contains : " << endl;
        for (int i = 0; i < size; i++)
        {
            cout << i << ": [" << oPtrDynamicArray[i] << "]" << endl;
        }
    } while (!endAdding);

    DeleteDynamicArray (oPtrDynamicArray, size);
}

int *CreateDynamicArray (int capacity, int &size)
{
    size = 0;
    return new int[capacity];
}

void DeleteDynamicArray (int *dynamicArray, int &size)
{
    delete[] dynamicArray;
    dynamicArray = nullptr;
    size = 0;
}

void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (&dynamicArray, size+1);
    }

    dynamicArray[size] = element;
    size++;

}

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int ** newArray = new int*[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = dynamicArray[i];
    }

    *dynamicArray = *newArray;

    delete[] newArray;
    newArray = nullptr;
}

The problem is that the array is passed to my InsertElement() function and then to ResizeDynamicArray() only if capacity <= size, but the array passed to the first function, is passed with good values, but with abnormal pointers in the array.

Example :

For an array of 3, I have :

array[0] = 1 --> adress 0x0004e300 containing value 1

array[1] = 2 --> adress 0x00000003 containing ???

array[2] = 3 --> adress 0x008ffb24 containing value 2

I really don't understand, it would be really great if someone could explain my error :/.

c++
visual-c++
c++17
asked on Stack Overflow Jun 30, 2019 by Walid M. • edited Dec 30, 2019 by Richard Chambers

3 Answers

1

The problem is here

void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (&dynamicArray, size+1);
    }
    dynamicArray[size] = element;
    size++;
}

when you call ResizeDynamicArray you are changing the dynamicArray pointer declared as a parameter to InsertElement. You are not changing the oPtrDynamicArray pointer in main.

If you want to make this work you need to change InsertElement to take a double pointer (just like ResizeDynamicArray)

void InsertElement (int **dynamicArray, int element, int &size, int capacity)
{
    if (capacity <= size)
    {
        ResizeDynamicArray (dynamicArray, size+1);
    }
    (*dynamicArray)[size] = element;
    size++;
}

Or you could do the easy thing and just use std::vector<int>.

EDIT now that I look at it your ResizeDynamicArray function I see that function is completely wrong as well. It's clear that you have some learning to do with pointers

Here's how ResizeDynamicArray should be

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int * newArray = new int[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = (*dynamicArray)[i];
    }

    delete[] *dynamicArray;
    *dynamicArray = newArray;
}

You're not the first newbie to fail to understand pointers. Have a good look at the code above and compare it with your code. The main difference is that my code using a pointer to change what is being pointed to. Your code tried to change the pointer itself, which is incorrect. It's confusing because what is being pointed to is another pointer (the dynamic array).

answered on Stack Overflow Jun 30, 2019 by john • edited Jun 30, 2019 by john
0

There are several issues in your code:

First, in ResizeDynamicArray, you allocate an array of pointers to ints, not an array of ints. int ** newArray = new int*[newCapacity] should be int *newArray = new int[newCapacity].

Second, once you have fixed that, you need to write *dynamicArray = newArray;; but you should free the old array before you assign the pointer to the new memory block.

void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
    int *newArray = new int[newCapacity];
    for (int i = 0; i < newCapacity; i++) 
    {
        newArray[i] = (*dynamicArray)[i];
    }

    delete[] *dynamicArray;
    *dynamicArray = newArray;
}

Third, you since InsertElement may call ResizeDynamicArray (which will give you back a new memory block), you need to alter the originally passed pointer. So you need to pass a pointer to a pointer int the function, just as you did with ResizeDynamicArray:

void InsertElement (int **dynamicArray, int element, int &size, int capacity)

adapt the body accordingly then.

answered on Stack Overflow Jun 30, 2019 by Stephan Lechner • edited Jun 30, 2019 by Stephan Lechner
0

I know the question is already answered but not the why.

You have to keep in mind that pointers are passed to functions by value. The pointer value, the address it points to, is lost when the function ends. But you are still able to change the value stored at the address it points to by dereferencing the pointer.

To pass be able to change the pointer value, the address it points to, inside a function, you have to pass a pointer to a pointer. In this case passing a double pointer is synonym for passing a pointer to a function by reference.

void Foo(int **ptr) 
{
    // Don't use ptr, changes are lost after function end as ptr is a local copy
    // Use *ptr to change the value of the pointer you passed to the function.
    // Use **ptr to change the value at the address the pointer you passed to the funcion points to
}

In this case you can change the pointer value, the address it points to, by dereferencing the double pointer once. Which applies to above answers.

answered on Stack Overflow Nov 18, 2020 by XLars

User contributions licensed under CC BY-SA 3.0