C. Binair
C. Binair

Reputation: 451

Pass dynamic arrays/matrices to functions for initialization

My question is basically a follow-up question of this question Proper way to pass dynamic arrays to other functions. Here the proper way for passing a dynamic array to a function is asked. Three options are given:

void test(bool arr[])
void test(bool *arr)
void test(bool *&arr)

The first two pass the pointer(of the array) by value and the second passes the pointer by reference. All can be used to change the content of the array as shown in alestanis' answer.

Now my question is what would be the correct way if you want to dynamically allocate the array inside the function. So something like this:

void init(double ?arr?, int n){
    arr = new double[n];
}

void main(){
    double * array;
    init(array,15);
}

I believe it works with the last syntax only, but I'm not sure.

Furthermore I would like to know how the last syntax would look like if you have a matrix. Would you have two &'s? Or is it just not possible?

P.S. I have vary large vectors and matrices so I would rather use regular array instead of std stuff. The size of the vectors and matrices are sort of input values for the user and the vectors and matrices are only created after input is complete so I never have the need to resize the vector/matrix.

Upvotes: 0

Views: 113

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

If you will pass a pointer by value then its changes of the pointer with the function do not influence on the original argument. The function will deal wuth a copy of the value of the original pointer.

So you have two approaches. The C++ approach is

void test(bool *&arr);

The C approach is

void test(bool **arr)

Here is a demonstrative program.

#include <iostream>
#include <iterator>
#include <numeric>

void init( double * &a, size_t n )
{
    a = new double[n];

    std::iota( a, a + n, 0.0 );
}

void init( double **a, size_t n )
{
    *a = new double[n];

    std::iota( std::reverse_iterator<double *>( *a + n ), std::reverse_iterator<double *>( *a ), 0.0 );
}

int main() 
{
    size_t n = 10;
    double *a = nullptr;

    init( a, n );

    for ( const double *p = a; p != a + n; ++p )
    {
        std::cout << *p << ' ';
    }

    std::cout << '\n';

    delete []a;
    a = nullptr;

    init( &a, n );

    for ( const double *p = a; p != a + n; ++p )
    {
        std::cout << *p << ' ';
    }

    std::cout << '\n';

    delete []a;
    a = nullptr;

    return 0;
}

Its output is

0 1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 0

If you want to allocate dynamically a two-dimensional array with a fixed number of columns then for example the function declarations can look the following way.

#include <iostream>
#include <iterator>
#include <numeric>

const size_t N = 5;

void init( double ( * &a )[N], size_t n )
{
    a = new double[n][N];

    for ( size_t i = 0; i < n; i++ )
    {
        std::iota( std::begin( a[i] ), std::end( a[i] ), i + i / 10.0 ); 
    }        
}

void init( double ( **a )[N], size_t n )
{
    *a = new double[n][N];

    for ( size_t i = 0; i < n; i++ )
    {
        std::iota( std::begin( ( *a )[i] ), std::end( ( *a )[i] ), i + i / 10.0 ); 
    }        
}

int main()
{
    double ( *a )[N] = nullptr;

    init( a, N );

    for ( size_t i = 0; i < N; i++ )
    {
        for ( const auto &item : a[i] )
        {
            std::cout << item << ' ';
        }

        std::cout << '\n';
    }

    std::cout << '\n';

    delete []a;
    a = nullptr;

    init( a, N );

    for ( size_t i = 0; i < N; i++ )
    {
        for ( const auto &item : a[i] )
        {
            std::cout << item << ' ';
        }

        std::cout << '\n';
    }

    std::cout << '\n';

    delete []a;
    a = nullptr;

    return 0;
}

The program output is

0 1 2 3 4 
1.1 2.1 3.1 4.1 5.1 
2.2 3.2 4.2 5.2 6.2 
3.3 4.3 5.3 6.3 7.3 
4.4 5.4 6.4 7.4 8.4 

0 1 2 3 4 
1.1 2.1 3.1 4.1 5.1 
2.2 3.2 4.2 5.2 6.2 
3.3 4.3 5.3 6.3 7.3 
4.4 5.4 6.4 7.4 8.4

Upvotes: 2

Related Questions