Manasa
Manasa

Reputation: 43

How to pass by reference a C++ array as a function parameter?

To pass by reference the C-style array as a parameter to a function, one needs to send the array size as a parameter to the function as well. The below code shows a function that accepts an array as pass by reference along with its size. Q1) Is there a way, we can pass arrays by reference without passing its size as well? Q2) If I were to overload the below function get_num_of_even_digited_input() to accept an array container (std::array) as the first parameter, what would the function prototype look like? (I mean how do I mention the size_t parameter for the array? Will it be int get_num_of_even_digited_input(array<int,??> )

int get_number_of_digits(int in_num)
{
    int input = in_num, rem = -1, dividend = -1, dig_count = 0;
    
    while(input)
    {
        dig_count++;
        dividend = input % 10;
        input = input/10;
    }

    return dig_count;
}

int get_num_of_even_digited_input(int arr[], int size_arr)
{
    int arrsize = 0, i = 0, count_of_evendigited_num = 0, count_of_dig = 0;
    arrsize = size_arr;

    for(i = 0; i < arrsize; i++, arr++)
    {
        count_of_dig = get_number_of_digits(*arr);
        if(count_of_dig % 2 == 0)
        {
            count_of_evendigited_num++;
        }
    }

    return count_of_evendigited_num;
}

void main()
{
    int array2[] = {23, 334, 4567, 1, 259};
    int sizearr2 = sizeof(array2)/sizeof(int);

    array<int, 6> array3 = {23, 5677, 564, 342, 44, 56778};

    cout << "Count of even digited numbers in array2[] : " << get_num_of_even_digited_input(array2, sizearr2) << endl;
    cout << "Count of even digited numbers in array3[] : " << get_num_of_even_digited_input(array3, array3.size) << endl; // HOW IS THIS FUNCTION PROTOTYPE GOING TO LOOK LIKE??
}

Upvotes: 0

Views: 3061

Answers (4)

6502
6502

Reputation: 114461

In C++ array size is a compile time concept because the size of the array is part of its type so it doesn't really makes sense to say that you have a function accepting arrays of different sizes at runtime.

You can write a function template that will accept arrays and that will expand to the specific version accepting a reference/pointer for a given array size. This is rarely a good idea because if you have say 10 different sizes for your arrays your compiled code would end up with 10 different copies of the same function. What the template strange syntax is saving you from is just writing those copies by hand.

What is normally done is writing a function that accepts a pointer to the first element and the number of elements at runtime, and then a small template wrapper that will just expand the call so that the size doesn't need to be passed explicitly:

int sum(const int *x, int n) {
    int s = 0;
    for (int i=0; i<n; i++) {
        s += x[i];
    }
    return s;
}

template<int N>
int sum(const int (&x)[N]) {
    return sum(x, N);
}

int foo() {
    int x[] = {1,2,3,4};
    return sum(x);
}

In the above code there will be only one copy of the function actually computing the sum of the elements and the template trick is used just to replace

sum(x);

with

sum(&x[0], 4);

automatically.

Even more frequently C arrays are replaced with std::vector for dynamic size containers and std::array for static size containers (the main advantage of std::array is that is a "normal" type that is handled like other C++ types and for example can be passed by value or can be returned from a function, something that doesn't work with C arrays).

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172864

You can make the parameter pass-by-reference, then no need to pass the size of array. (When passing by-reference, raw array won't decay to pointer and its size is reserved.) And also make the function template, then it can work with both raw arrays and std::array.

template <typename T>
int get_num_of_even_digited_input(const T& arr)
{
    int count_of_evendigited_num = 0;

    // I use range-based for loop here
    // you can get the size of the array as std::size(arr) if necessary
    // it works with raw arrays and std::array too
    for (auto e : arr)
    {
        if(get_number_of_digits(e) % 2 == 0)
        {
            count_of_evendigited_num++;
        }
    }

    return count_of_evendigited_num;
}

Upvotes: 1

tdao
tdao

Reputation: 17678

Is there a way, we can pass arrays by reference without passing its size as well?

It's not mandatory to pass the array size. You can pass the array only, but you have to be sure you don't operate out-of-bound. The size there is to help the user of the function to do just that (ie operating in safe manner).

Alternatively, and better, use std::vector instead. You should never to worry about the size anymore as that information comes from the input vector itself.

what would the function prototype look like?

When you use vector, the prototype can be:

int get_num_of_even_digited_input(std::vector<int>& param)

As said you don't need to pass the size anymore, because you can always use param.size() to find out how many items are there.

Also if you don't change the param inside that function, then use const std::vector<int>& param instead.

Upvotes: 1

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29955

Yes:

template<auto size>
void foo(int (&arr)[size]);

The STL way of doing this would be to pass begin/end iterators:

template<typename Iter>
void foo(Iter begin, Iter end);

Or use std::span in C++20.

Upvotes: 1

Related Questions