Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must the expanded array be dynamically allocated for this function to work properly C++

I have been working on a function that accepts an array and an array size as an argument. The functions task is to create a second array that is twice the size of the fist array, copying the elements of the first array into the first half of the second array, and initializing the remaining elements to zero.

I can only get this to work if I dynamically allocate the second array with in the function. I suspect this is because once a function returns control to the calling function, any array that is not dynamically allocated is deleted from memory. In other words, the pointer in the calling function will point to junk data because the second array that was created in the expander function is now gone. Can anyone confirm this?

Here is the function written two different ways.

This way works

int *array_expander(int array[], int size)
{

    int *new_array = new int[size*2];

    for(int i{0}; i < size; i++)
        *(new_array + i) = *(array + i);

    for(int i{size}; i < size * 2; i++)
        *(new_array + i) = 0;

    return new_array;
}

This way doesn't

int *array_expander(int array[], int size)
{
    int new_array[size * 2];

    for(int i{0}; i < size; i++)
        *(new_array + i) = *(array + i);

    for(int i{size}; i < size * 2; i++)
        *(new_array + i) = 0;

    int *arr_ptr = new_array;

    return new_array;
}
like image 840
Tcrumb Avatar asked Mar 03 '23 02:03

Tcrumb


1 Answers

You are right. You may not return a pointer to a local object with the automatic storage duration from a function because the returned pointer will be invalid due to the fact that the local object will not be alive after exiting the function.

Moreover variable length arrays is not a standard C++ feature. So this statement

int new_array[size * 2];

can not be compiled by a compiler that does not have its own corresponding language extension.

As for the function then it should be declared like

int * array_expander( const int array[], size_t size );

You should add the qualifier const to the first parameter because the passed array is not changed in the function.

The function can be implement by using standard algorithms as it is shown in the demonstrative program below.

#include <iostream>
#include <algorithm>

int * array_expander( const int array[], size_t size )
{
    int *new_array = new int[ 2 * size ];

    std::fill_n( std::copy( array, array + size, new_array ), size, 0 );

    return new_array;
}

int main() 
{
    int a[] = { 1, 2, 3, 4, 5 };
    const size_t N = sizeof( a ) / sizeof( *a );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    int *new_array = array_expander( a, N );
    size_t n = 2 * N;

    for ( size_t i = 0; i < n; i++ ) 
    {
        std::cout << new_array[i] << ' ';
    }
    std::cout << '\n';

    delete [] new_array;

    return 0;
}

The program output is

1 2 3 4 5 
1 2 3 4 5 0 0 0 0 0 

Pay attention to that instead of arrays you could use the standard container std::vector.

like image 194
Vlad from Moscow Avatar answered Apr 05 '23 23:04

Vlad from Moscow