Reputation: 43
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
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
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
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
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