Everything but arrays in c++ are passed by value by default? - c++

Everything in c++ , including the STL containers are passed by value . But the exception is Array which are passed by pointers . Right?
Why are arrays in c++ [eg: int a[5] ] are passed by pointers but the vectors are passed by value ? [By default]
edit: okay , std::array can be passed by value also , I wasn't aware of this .
code :
void fun_array(int a[])
{
a[0]=10;
}
void fun_vector(vector<int> v)
{
v[0]=10;
}
int main()
{
int a[5]={1,2,3,4,5};
vector<int> v={1,2,3,4,5};
fun_array(a);
fun_vector(v);
cout<<a[0]<<" "<<v[0];
}
output : 10 1

Everything is passed by value if you don't specify otherwise. The case about C arrays is not an exception, but just that they degenerate into pointers. If you need a fixed size array in C++ code prefer using std::array instead of C arrays.
Then decide if you want to pass by value or by reference.
Related note: Even when passing containers, you might still want to pass by value, instead of by reference, if you are going to copy the container.

By default all function arguments in C++ are passed by value.
Your confusion comes from the fact that the name of an array is actually a pointer to the first element of the array (eg. for the array int a[6], a is a pointer to a[0].
Unless the function parameter is explicitly a reference to a pointer, even pointer arguments are passed by value.

Related

While passing an array through a function in C++/C, why address of array is used in actual parameter whereas the array in formal parameter?

#include <iostream>
using namespace std;
int func(int ar[5]){
//the code is written here with returning whatever the requirement is
}
int main(){
int ar[5];
func(ar);
return 0;
}
In this kind of situation where we are passing array through a function why the address of the array is used in actual parameter whereas the array in formal parameter?
This is because C handled arrays weirdly.
In C, arrays convert to a pointer to their first element at the drop of a hat, cannot be passed as arguments to a function, cannot be returned from functions, and cannot be copied by assignment.
C++, originally based off C, carries these screwed up design decisions as a legacy issue. Fixing them would break insane amounts of code.
If you want an array that behaves more reasonable, use std::array.
void foo(int[5]);
this is actually taking an int* argument.
int arr[7];
foo(arr);
this converts the 7 element arr to a pointer and passes it to foo. Which seems to take int[5] but that 5 does nothing.
Yes this is utterly crazy.
Now,
void bar(int(&)[5])
because C does not have references, the above is an actual reference to an array if 5 elements, so
bar(arr)
won't compile.
There is nothing weird, nor screwed up about how arrays are passed in C. C is expressed pretty simply, really. C /does/ have references; they are explicit, so, easy to see when they're in use. We call them pointers.
One simply needs to understand that there is not dedicated storage for array types, that arrays are not first-class types, so, won't behave like first-class types. Can't be assigned into (directly), nor passed into and out of functions directly.
In C/C++ we use pointers to refer to a chunk of memory where the contents of the array are stored.
So, all that's left is that we understand that when we declare an array, the name of the array is really a pointer to the beginning of the array.
int a[12] ;
/* a's type is this: */
int *a ;
So, when we "pass an array" to a function, we are copying the pointer into the function. The semantics are straightforward, and entirely consistent (unlike Java).
The array, itself, is never passed directly.
Finally, realise that there is no difference between a pointer to a single integer, and a pointer to a contiguous chunk of integers in memory.
Remember, a[i] is equivalent to *(a+i). So, in this example:
int i = 12 ;
int *p = &i ;
, *p is the same as *(p+0); the p can be thought of as an array of length 1.
With a slight change in perspective you should be able to see the simplicity, the elegance, that is C.

I have a question about passing std::array into function

I'm learning c ++ And the syntax of putting a std::array into the function confuses me.
#include <iostream>
#include <array>
using namespace std;
void printArray(const std::array<int, 5> &n)
{
std::cout << "length: " << n.size() << endl;
for (int j = 0; j < n.size(); j++ )
{
cout << "n[" << j << "] = " << n[j] << endl;
}
}
int main()
{
array<int, 5> n = {1,2,3,4,5};
printArray(n);
return 0;
}
I want to ask about 'const', what role does it play and what effect does it have if not using it?
Why do we have to use &n while the name of an array is already pointer
Depending on the argument you can do certain assumptions about the function.
void printArrayA(std::array<int, 5> n)
If I call printArrayA then the array I pass to it is copied, so the function can't do changes to the array I pass, but has an overhead of copying the array.
void printArrayB(std::array<int, 5> &n)
If I call printArrayB then the array I pass to it is not copied, the function could do changes on the array, or on the elements stored in the array.
void printArrayC(const std::array<int, 5> &n)
If I call printArrayC then the array I pass to it is not copied, and because it is const the function can't do any changes on that array or on its elements. (Well I, in theory, could cast away the const, but that's not something that should be done, a const should indicate the caller, that the object won't be changed)
void printArray(const std::array<int, 5> &n)
What this does is to allow you to pass in to the function an unchangeable (without const-casting it, anyway) reference to the std::array. The reference is a lot smaller than the array itself, typically just a pointer, and the const bit ensures the function does not attempt to change the underlying object.
It's usually used to ensure you don't copy "large" things where unnecessary, things like vectors, arrays or strings.
In this case const means that printArray will not modify the object passed to it.
An std::array is not a C-style array (such ase int a[10]), so you are not passing a pointer, you are passing a reference to an std::array object.
Your question is not only about 'std::vector', it is about 'const' and 'references'.
'const' keywords means that you can call only 'const' method of that class, means that (assume that the used class is implemented correctly) you can't modify this class in that method.
'&' means that you pass the parameter by 'reference' and not by 'value', if you are not familiar with that difference you may want to read this: Value vs. Reference
As others have mentioned, the name of a std::array does not decay to a pointer. To convert to a pointer, you would call .data().
Why do you want to pass by (const) reference, and why does a foo[]decay to a foo* const in many contexts?
You (practically) never want to copy arrays. It takes a huge amount of time and memory. You always want to pass them to a function by reference. On top of that, most algorithms that work on arrays are supposed to work on arrays of any size. (Brian Kernighan, the K in K&R, particularly considered it a flaw in Pascal that the size of an array is part of its type.) Therefore, back in the ’70s, the designers of C made a rule that passing an array to a function is the same as passing a pointer to its first element.
C++ stuck with that for the sake of backward compatibility: a lot of programmers compile C code in C++ compilers. One famous pitfall is trying to take the sizeof an array parameter in C++. Because array parameters decay to pointers, this gives you the size of a pointer. In C++, you have the option of passing a type (&name)[size] instead; that is, passing a type[size] by reference. This preserves the size as part of the type. (C also got some new syntax in 1999 that never made it over to C++, including the ability to pass the size of an array parameter.)
In C++, a std::array has no special syntax and works like any other type. You never want to copy an entire array that you aren’t going to modify. You still want to pass arrays by reference, so you use the standard syntax for that: &. Whenever you don’t need to modify a parameter, you declare it const. This helps the compiler detect logic errors and, sometimes, optimize.

Passing array of vectors as a function parameter to change the original values

I have an array of vectors (of ints) and I want to pass it to a member function as reference so it can be modified. (It actually is the output of my function but I already have a return value.)
I wrote something like this
int Dag::dag2array(vector<int> (&aVectors)[4])
{
//some stuff
//calling another function tree2array(aVectors)
//passing the same array as reference
}
It compile and runs although it looks like it is not doing what I want.
In a more or less opposite question (Passing array of vectors as a function parameter (values will not change)), the answers say that the array can be modified without & and that it does not make a copy but it is like a pointer.
Why for a variable like an int one needs the & to avoid
copying and to be able to modify the value of the original variable "on the fly" and not for an array?
Should I use the & or not in my case?
This is one of those cases where C arrays just make life difficult. I would strongly recommend using a std::array (or std::tr1::array if you're not using C++11 yet). Rather than that obscure syntax, saying
int func(std::array<std::vector<int>, 4>& vectors)
makes it very clear that you're passing an array of 4 vectors by reference, and thus can modify the values by saying
vectors[1][2] = 19;
or what-have-you.
When an array is passed to a function, its type is adjusted to a pointer to its first element. Likewise a parameter declaration of the form T[N] is adjusted to T*. The pointer being passed is copied but the elements of the vector are not copied at all. This means when dereferencing the pointer you can still refer to the original array element through the array access syntax array[n] (which is really just pointer arithmetic: *(array + n)).
If you are passing an actual object to a function by value, a copy will occur so if you still want to modify the element you will need a reference.
So no, you do not need to pass the array by reference. Not unless you want to access the size of the array in the function (because the array-to-pointer decay discards the array size).

Is C++ Array passed by reference or by pointer?

In school, our lecturer taught us that the entire array was passed by reference when we pass it to a function,.
However, recently I read a book. It says that arrays are passed by pointer by default when passing the entire array to a function. The book further mention that "passing by pointer is very similar to passing by reference", which means that passing by pointer and passing by reference are actually different.
It appears that different source stated differently.
So my question is: In C++, are arrays passed by reference or by pointer when we pass the entire array to a function?
For Example:
void funcA(int []); //Function Declaration
int main()
{
int array[5];
funcA(array); //Is array passed by ref or by pointer here?
}
At worst, your lecturer is wrong. At best, he was simplifying terminology, and confusing you in the process. This is reasonably commonplace in software education, unfortunately. The truth is, many books get this wrong as well; the array is not "passed" at all, either "by pointer" or "by reference".
In fact, because arrays cannot be passed by value due to an old C restriction, there is some special magic that happens with arrays as function arguments.
The function declaration:
void funcA(int[]);
is silently translated into the following:
void funcA(int*);
and when you write this:
funcA(myArray);
it is silently translated into the following:
funcA(&myArray[0]);
The result is that you're not passing the array at all; you pass a pointer to its first element.
Now, at certain levels of abstraction/simplification, you can call this "passing an array by pointer", "passing an array by reference" or even "passing a handle to an array", but if you want to talk in C++ terms, none of those phrases are accurate.
The terminology used by your lecturer is confusing. However, in a function declaration such as
void funcA(int []);
the int[] is just another way of saying int*. So funcA can take any argument that is or can be converted to an int*.
Arrays can decay to pointers to the first element in the right context. This means, for example, that you can assign an array's name to a pointer like this:
int array[42]; // array is of type int[42]
int * arr = array; // array decays to int*
So, when you pass array to funcA,
funcA(array); // array decays to int*
funcA has a pointer to the first element of the array.
But it is also possible to pass arrays by reference. It just requires a different syntax. For example
void funcB(int (&arr)[42]);
So, in your example, you are passing a pointer to the first element of the array, due to the signature of your function funcA. If you called funcB(array), you would be passing a reference.
Pass-by-pointer is a bit of a misnomer. It doesn't happen in C++. There is only pass-by-value and pass-by-reference. Pointers in particular are passed by value.
The answer to your question is: it depends.
Consider the following signatures:
void foo(int *arr);
void bar(int *&arr);
void baz(int * const &arr);
void quux(int (&arr)[42]);
Assuming you are passing an array to each of these functions:
In foo(arr), your array is decayed to a pointer, which is then passed by value.
In bar(arr), this is a compiler error, because your array would decay to a (temporary) pointer, and this would be passed by reference. This is nearly always a bug, since the reason you would want a mutable reference is to change the value of the referent, and that would not be what would happen (you would change the value of the temporary instead). I add this since this actually does work on some compilers (MSVC++) with a particular extension enabled. If you instead decay the pointer manually, then you can pass that instead (e.g. int *p = arr; bar(p);)
In baz(arr), your array decays to a temporary pointer, which is passed by (const) reference.
In quux(arr), your array is passed by reference.
What your book means by them being similar is that passing a pointer by value and passing a reference are usually implemented identically. The difference is purely at the C++ level: with a reference, you do not have the value of the pointer (and hence cannot change it), and it is guaranteed to refer to an actual object (unless you broke your program earlier).

Changing of the size of integer array when passing by value [duplicate]

This question already has answers here:
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 9 years ago.
I'm just curious what is the reason for the following error: I'm trying to determine the size of an integer array.
When I find the size of array in main function, this code returns correctly:
int program[12] = { 1007, 1008, 2007, 3008, 2109, 1109, 4300, 0, 0, 0, -99999 };
cout<<sizeof(program)/sizeof(program[0])<<"\n";
But if I pass program to a function by value, it always return 2:
void Sipmletron::load(int program[])
{
int length=sizeof(program)/sizeof(program[0])
std::cout<<length<<"\n";
memory= new int[length];
}
You cannot pass arrays by value. The argument is passed as a pointer to the first element of the array, so you are in effect calculating sizeof(int*) / sizeof(int).
When an array is passed in C++ (and in C), it looses it's size (it's passed as the address of the first element, no matter whether it is int * or int []).
You can use std::array if you are using C++11, which has a size() member function, similar to vector. In almost all other aspects, it is the same as a standard C style array.
Otherwise, you have to pass the size along with the array - or use some marker to indicate the end (looks like you already have that with -99999).
There are two special-case language rules at play here, both inherited directly from C.
An expression of array type, in most contexts, is implicitly converted to ("decays to") a pointer to the array's first element. The exceptions in C are when the expression is the operand of unary & or sizeof, or when it's a string literal in an initializer used to initialize an array (sub)object. C++ has more exceptions, but none that apply here.
A parameter defined as some_type foo[] is "adjusted" to some_type *foo, so your parameter program is really a pointer, not an array. (This adjustment occurs only for parameter declarations.)
These rules (unfortunately IMHO) work together to make it appear that you're passing an array object by value, and accessing an array inside your function, but in fact it's all pointers.
You could do this with templated member functions if you really wanted to:
template <size_t N>
void Sipmletron::load(int (&program)[N])
{
size_t length = N;
std::cout << length << "\n";
memory = new int[length];
}
In addition, and even without seeing the rest of your code, I'm feel sure it would be worth your while looking at using a std::vector instead of doing your own memory management using new, with a more idiomatic load(...) that used iterators.