What is the second parameter passed to these functions? [duplicate] - c++

This question already has answers here:
Passing an array by reference
(5 answers)
Closed 6 months ago.
void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
In those function overloads but what exactly are the second parameters.
My guess is,
#1 any empty array
#2 Returns the reference of the first index of an array

Both are references to arrays of the written type and size.
For example const int (&)[2] is a const lvalue reference to an array of 2 int (or equivalently a lvalue reference to an array of 2 const int).
The first one has a default argument which would create a temporary array of the given type to which the reference binds if no argument is provided in a call. That temporary array would be initialized as if by a = {} initializer. (In the case of type int this means the elements are zero-initialized.)

Related

Why is that you can modify an array inside a function without using any reference or pointer [duplicate]

This question already has answers here:
Array changed in a void function, is still changed outside! why? (scope)
(4 answers)
Passing an array as a parameter in C
(3 answers)
Passing Arrays to Function in C++
(5 answers)
Passing an array as an argument to a function in C
(11 answers)
Closed 11 months ago.
I don't get it why you can alter the values inside the array, without using a reference or a pointer (&, *), I'm a freshmen student, and I don't know the reason behind, I hope someone can provide a logical answer, please refer to the code below, Thank You in Advance.
#include <iostream>
using namespace std;
void a(int x[]){
for(int i = 0; i < 5; i++){
x[i] += 2;
}
}
int main(){
int x[5] = {1,2,3,4,5};
a(x);
for(auto b : x){
cout << b << " ";
}
return 0;
}
A function parameter is never an array in C++. When you declare a function parameter as an array, it is automatically adjusted to be a pointer to element of such array. These declarations are effectively identical:
void a(int x[]); // looks like an array of int of unknown bound
void a(int* x); // declaration above is adjusted to this
void a(int x[1234]); // the size is ignored completely
An array implicitly converts to a pointer to the first element of the array (such conversion is called decay). Hence, you can call the function that doesn't accept an array parameter by passing an array argument:
int* ptr1 = x; // implicit conversion
int* ptr2 = &x[0]; // same conversion explicitly
a(x); // same conversion happens here
These two rules (function parameter adjustment and array to pointer decay) make it so that what syntactically looks like passing arrays by value, is actually done using indirection. Within the function, you modify the elements by indirecting through the pointer parameter that points to the array that exists outside of the function.
Important note: The adjustment of array to pointer in function parameter does not apply in other contexts. Arrays and pointers are distinct types with different properties.
Another note: The adjustment does not apply to parts of compound types. For example, a function parameter of type "pointer to array" will not be adjusted to be "pointer to pointer" and "reference to array" will not be adjusted to be "reference to pointer".
The parameter having the array type in this function declaration
void a(int x[]){
is adjusted by the compiler to pointer type to array elements type. That is the above declaration is equivalent to
void a(int *x){
In this call of the function
a(x);
the array designator is implicitly converted to pointer to its first element. That is the call is equivalent to
a( &x[0]);
So within the function you have a pointer to the first element of the array declared in main.
Using the pointer arithmetic you can access elements of the array. That is the elements of the array are passed to the function by reference in the C meaning indirectly through a pointer to them.
Within the function the variable x has the type int *. And this expression statement
x[i] += 2;
is equivalent to
*( x + i ) += 2;
Beacuse
void a(int x[]){
is the same as
void a(int *x){
and so you are using a pointer
Why?
Because an array like
int x[10];
'decays' to a pointer when passed to a function (and in other places). This can be very confusing but at the same time is very flexible
It mens that I can have a function like strlen that can accpet a 'real' array, or a pointer. These 'strings'
char *s1 = malloc(10);
strcpy(s1, "hello");
char s2[] = "hello";
char *s3 = "hello";
store their data in different ways but all can be handled by
size_t strlen(const char *s);
note that this is exactly the same as
size_t strlen(const char s[]);
they are 2 different ways of writing the same thing. Personal preference is for the second type if its really is an 'array' vs a pointer to maybe an array.
One issue with this 'decay' is that inside strlen (or any pointer/array accepting function) it is impossible to 'know' the length just from the parameter. The compiler knows that the size of s2 is 6 but this information is not carried forward to the function.
Regularly SO sees this
void my_func(int *arr){
int len = sizeof(arr)/sizeof(arr[0]);
....
}
int a[10];
my_func(a);
This will give len = 1 or 2 (depending on 32 or 64 bit machine), never 10
The flexibility costs a litle power

How do I pass an array as an reference to a pointer of const char? [duplicate]

How does passing a statically allocated array by reference work?
void foo(int (&myArray)[100])
{
}
int main()
{
int a[100];
foo(a);
}
Does (&myArray)[100] have any meaning or its just a syntax to pass any array by reference?
I don't understand separate parenthesis followed by big brackets here. Thanks.
It's a syntax for array references - you need to use (&array) to clarify to the compiler that you want a reference to an array, rather than the (invalid) array of references int & array[100];.
EDIT: Some clarification.
void foo(int * x);
void foo(int x[100]);
void foo(int x[]);
These three are different ways of declaring the same function. They're all treated as taking an int * parameter, you can pass any size array to them.
void foo(int (&x)[100]);
This only accepts arrays of 100 integers. You can safely use sizeof on x
void foo(int & x[100]); // error
This is parsed as an "array of references" - which isn't legal.
It's just the required syntax:
void Func(int (&myArray)[100])
^ Pass array of 100 int by reference the parameters name is myArray;
void Func(int* myArray)
^ Pass an array. Array decays to a pointer. Thus you lose size information.
void Func(int (*myFunc)(double))
^ Pass a function pointer. The function returns an int and takes a double. The parameter name is myFunc.
It is a syntax. In the function arguments int (&myArray)[100] parenthesis that enclose the &myArray are necessary. if you don't use them, you will be passing an array of references and that is because the subscript operator [] has higher precedence over the & operator.
E.g. int &myArray[100] // array of references
So, by using type construction () you tell the compiler that you want a reference to an array of 100 integers.
E.g int (&myArray)[100] // reference of an array of 100 ints
The following creates a generic function, taking an array of any size and of any type by reference:
template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
// do stuff
}
play with the code.
Arrays are default passed by pointers. You can try modifying an array inside a function call for better understanding.

Modifying const returning from function [duplicate]

This question already has answers here:
Purpose of returning by const value? [duplicate]
(4 answers)
Closed 6 years ago.
I think I haven't grasped the proper idea behind returning something that is const.
If I'm having a function which returns const value, doesn't it means that I cannot change the value after I returned it?
Why the compiler allows me to cast my const to a non-const variable?
Or it works only with const pointers?
const int foo(int index) {
return ++index;
}
int main(){
int i = foo(1); // why can I do this?
++i;
return 0;
}
You're doing the equivalent of this:
const int a = 42; // a cannot be modified
int b = a; // b is a copy of a...
++b; // and it can be modified
In other words, you are making a copy of a const object, and modifying said copy.
Note that returning a const value has limited, ehm, value. For built-in types it isn't important. For user-defined types, it can prevent modifying a "temporary" object, at the cost of preventing move semantics. Since C++11 it has become advisable to not return const values.

Function omit struct [duplicate]

This question already has answers here:
Default argument for structure reference in C++
(5 answers)
Closed 9 years ago.
it is possible for a function to not have some struct info? Something like this
int f(int x,int y=1) and calling f(2) it's just fine but for this int f(int x,struct my_struct &y)
what's the correct way considering that it's a reference there?
Since it is a non-const reference, you can't bind it to a default value which is a temporary object. You could bind it to some non-temporary object like so:
my_struct obj;
int f(int x, my_struct& y = obj) {
// ...
}
But this would mean that every invocation of f without a second argument would have access to the same obj. They could each modify it and then the next would receive an obj with a different state. This isn't very typical of default values. You expect it to have the same default value each time.
Why would your function take an object by non-const reference if it were possible to not pass an object? You take a non-const reference when you want the caller to pass an object for you to modify.
It may make more sense for your y parameter to be a const reference instead. You take a const reference when you want the caller to pass you an object for you to observe and you don't want to copy it. Then you could bind it to a temporary object like so:
int f(int x, const my_struct& y = my_struct(1, 2, "some args")) {
// ...
}

In regards to array size calculation [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can someone explain this template code that gives me the size of an array?
Hi, I am looking at the answer posted here:
Computing length of array
Copied here:
template <typename T, std::size_t N>
std::size_t size(T (&)[N])
{
return N;
}
Can some one pls explain me the significance of (&) ?
The & says the array is passed by reference. That prevents the type from decaying to pointer. Without passing by reference you would get that decay, and no information about the array size.
Non-template example:
void foo( int (&a)[5] )
{
// whatever
}
int main()
{
int x[5];
int y[6];
foo( x ); // ok
//foo( y ); // !incompatible type
}
Cheers & hth.,
The & means that the array is to be passed by reference. Arrays can't be passed by value, because in this case they decay to a pointer to the first item. If that happens, the size information associated with the array type is lost.
It is in parenthesis, because otherwise that would mean the function accepts a pointer to reference. Although such a thing is not legal in C++, the syntax is consistent with how you declare a pointer to array.
int (*arr)[3]; // pointer to array of 3 ints
int* p_arr[3]; // array of pointers
int (&arr)[3]; // reference of array of 3 ints
int& r_arr[3]; //array of references (not legal in C++)