Do I need to put "&" when I pass a 2D array to a function or 2D arrays automatically do so by reference as 1Ds.
void fnc (int& arr[5][5]) {
}
It will be passed by value if you don't specify pass by reference &.
However arrays decay to pointers, so you're basically passing a pointer by value, meaning the memory it points to will be the same.
In common terms, modifying arr inside the function will modify the original arr (a copy is not created).
Also, 1D arrays also aren't passed "automatically" by reference, it just appears so since they decay to pointers.
If you really want to pass the array by reference it would need to be:
void fnc(int (&arr)[5][5]);
Without the inner parentheses, as Mr Anubis says, you will be attempting to pass an array of references which is unlikely to be helpful.
Normally one would just write
void fnc(int arr[][5]);
(You could write arr[5][5], but the first 5 is ignored which can cause confusion.)
This passes the address of the array, rather than the array itself, which I think is what you are trying to achieve.
You should also consider a vector of vectors or other higher-level data structure; raw arrays have many traps for the unwary.
Related
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).
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).
I have one quick question about the passing of arrays in C++ which I don't understand.
Basically when you want to pass a array of type integer to another function you have to pass an address to that array instead of directly passing the whole block of contiguous memory. Exactly why is the case?
Also, why is that char arrays can directly be passed to another function in C++ without the need to pass an address instead??
I have tried looking for learning materials for this online (such as cplusplus.com) but I haven't managed to find and explanation for this.
Thanks for your time, Dan.
As long as C++ is concerned, passing char arrays and int arrays are same.
There are 2 ways to pass arrays in c++.
Address is passed
int fn(int *arrays, int len);
int fn(int arrays[], int len); // Similar to above, still staying as sytax hangover from anci c
Array reference is passed
int fn(int (&array)[SIZE]); // Actual array passed as reference
You can templatized above function as
template<size_t SIZE>
int fn(int (&array)[SIZE]);
Above method allows you to pass array of anysize to this function. But beware, a different function is created from template for each size. If your function's side effect changes a local state (static variable for ex), this should be used with care.
If you don't want to change contents, use const with arguments.
If you want a copy of array in function argument, consider using stl container like std::array or std::vector or embed array in your class.
It isn't entirely clear from your question exactly what you're trying and what problems you've had, but I'll try to give you useful answers anyway.
Firstly, what you're talking about is probably int[] or int* (or some other type), which isn't an array itself... its a pointer to a chunk of memory, which can be accessed as if it were an array. Because all you have is a pointer, the array has to be passed around by reference.
Secondly, passing around an array as a "whole block of contiguous memory" is rather inefficient... passing the point around might only involve moving a 32 or 64 bit value. Passing by reference is often a sensible thing with memory buffers, and you can explicitly use functions like memcpy to copy data if you needed to.
Thirdly, I don't understand what you mean about char arrays being "directly" passable, but other types of arrays cannot be. There's nothing magic about char arrays when it comes to passing or storing them... they're just arrays like any other. The principle difference is that compilers allow you to use string literals to create char arrays.
Lastly, if you're using C++11, you might want to consider the new std::array<T> class. It provides various handy facilities, including automatic memory management and keeping track of its own size. You can pass these by value, template<class T> void foo(std::array<T> bar) or by reference template<class T> void foo(std::array<T>& bar), as you like.
You can't pass any array by value. You can pass by value either a struct containing array or std::array from C++11.
I've been studying along with the Stanford courses on iTunes U and have hit pointers in C++. I think I understand how pointers work, but I just want to check how to do some simple stuff. Let's say I want to create a dynamic array:
double *array;
At this point there's a variable called "array" in the stack and nothing in the heap. First question - what's stored in "array" at this point? A pointer to some nonsense piece of memory?
I then allocate memory using "new":
array = new double[10];
Second question - at this point, what's stored in "array"? A pointer to some contiguous piece of memory big enough to hold ten doubles? (Sorry for the simple questions, but I really want to make sure I understand)
I assign the double 2.0 to each element in the array:
for(int i=0; i<array.length(); i++) array[i]=2.0;
Third question - is this different from using the dereference operator to assign? (i.e., *array[i]=2.0). I then pass the array to some other function:
myFunc(double array[]){
for(int i=1; i<array.length(); i++){
array[i]=array[i]*array[i-1];
}
}
Fourth question - on the pass to myFunc, since array is an array of pointers to doubles, and not an array of doubles, it passes by reference without "&", right? That means the operations in my loop are affecting the actual data stored in "array". What if I wanted to pass by value, so that I wouldn't be touching the data in "array"? Would I use
myFunc(double *array[]){...}?
Last question - what if I wanted to manipulate the memory addresses for the contents of "array" for some reason? Could i use
someVar = &array[5];
to assign the the hex address of array[5] to someVar?
I've read the section on pointers in the reader and watched the Binky video a dozen times and it still doesn't make sense. Any help would be greatly appreciated.
EDIT: Thanks a lot to everyone who answered so far. If you wouldn't mind I just have one more question. In the declaration double *array;, "array" is declared as a pointer to a double, but once I use "new" to assign it, "array" ceases being a pointer to a double, and becomes an array of doubles, right?
array contains junk data - whatever was in that memory location before array existed is still there. If you try to play with it you're going to shoot yourself in the foot, which is why you need to assign it to a valid memory location, (hence the ensuing call to new[]).
Yes, array now contains a pointer (memory address) to some contiguous piece of memory big enough to hold ten doubles.
*array[i]=2.0 won't actually compile. array[i] results in a double, and you can't use the dereference operator on a double.
What you're passing is that address to the first element in the array. So you are passing the pointer by value, and the array by reference (as the pointer is a reference to the array.) To pass the array itself by value you'd have to have one parameter for each entry. You could also copy the array and send in the copy, but the copy itself would be passed by reference, too.
double* someVar = &array[5]; will return to you a pointer to the 6th element of the array. array[5] gives you the double, and taking the address of it (with &) will give you the memory address (pointer) of that double.
Yep, that's what's happening
Most definitely. More specifically, a pointer to the beginning of a contiguous piece of memory.
Not in this case; * (for dereference) is a unary operator, and yet you have passed it two arguments. You can be sure it is multiplication that is performed (or an overloaded version of it) - also, what could array[i](*array[i-1]) mean? you can't dereference something that isn't a pointer (or doesn't have the unary * operator overloaded)
You're only passing the pointer by value and not the data. If you want to pass the data by value (make it unchanged outside the function), you'd have to copy it first, and pass that (or just use a vector)
Yes, you're just getting the address of a part of contiguous memory, and you can store the address and modify the dereferenced value elsewhere, the array will be modified also.
Also, be weary that when you allocate on the heap, you have to delete the memory afterwards. In this case, you would use delete[] array;
After declaration, the array variable contains an arbitary value. You're not allowed to do anything with that value. After new, it contains a pointer to a contiguous range of memory large enough to hold 10 doubles. *array[i]=2.0 is an error (that would imply that array is an array of pointers to double). Indexing operator [] is just a syntactic sugar for *(array+i)=2.0.
Forth question: SAY WHAT?? You don't have an array of pointers to doubles anywhere in that code. In functions, void f(double *x) and void f(double x[]) are THE SAME THING: a pointer to double. If you pass to f an array, x will receive the address of the first element (which is the VALUE of an array).
You can't pass arrays by value. Alternatively, they are always passed by value (as everything else in C), but note that the VALUE of an array is the address of its first element.
Your last question: I have no idea what you're trying to achieve, but the question clearly shows that you're confused. An address is an address, there's no such thing as "hex address".
My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function.
I have some really big vectors that I'm passing around in my program. All the vectors will be modified inside the functions. My matrices are of sizes about [256*256][256][50]...
Is there some particular reason not to use call-by reference here?
AFAIK call by reference should be way faster and consume less memory?
Besides all common discussions on when and how to pass by possibly const reference for non-primitive types, arrays are quite special here.
Due to backwards compatibility with C, and there due to your specific problem: arrays can be huge, arrays are never really passed by value in either C or C++. The array will decay into a pointer to the first element, so when you write:
void foo( type array[100] );
The compiler is actually processing:
void foo( type *array );
Regardless of what the size of the array is (two common pitfalls there: trusting that array is an array inside foo and believing that it will be guaranteed to be 100 elements on it.
Now, in C++ you can actually pass arrays by reference, but the reference must be of the concrete type of the array, that includes the size:
void foo_array( type (&array)[100] );
The funny syntax there is telling the compiler that the function will take an array of exactly 100 elements of type type. The advantage there is that the compiler can perform size checking for you:
// assuming 'type' is defined
int main() {
type array0[99];
type array1[100];
foo( array0 ); // compiles, but if size=100 is assumed it will probably break
// equivalent to: foo( &array0[0] )
// foo2( array0 ); // will not compile, size is not 100
foo2( array1 ); // compiles, size is guaranteed to be 100
}
Now, the problem is that your function will only work for an array of exactly 100 elements, and in some cases, you might want to perform the same operation in different array sizes. The two solutions are: template the function in the size of the array which will provide a size-safe implementation for each used size --greater compile time and binary size, the template is compiled for every different size-- or using the pass-by-value syntax, which will make the array decay --not safe in size, that must be passed as extra argument, lesser compile time and binary size. A third option is combining both:
void foo( type *array, int size );
template <size_t N>
void foo( type (&array)[N] ) {
foo( array, N );
}
In this case, while there will be one templated foo for each size, the compiler will most probably inline the call and the generated code would be equivalent to the caller providing the array and size. No extra computations needed and type safety for real arrays.
Now, pass-by-reference is very rarely used with arrays.
My teacher in c++ told me that call by reference should only be used if I'm not going to change anything on the arrays inside the function.
It should be used when you are not changing something inside the function or you change things and want the changes to be reflected to the original array or don't care about the changes to be reflected in the original array.
It shouldn't be used if you don't want your function to change your original array (you need to preserve the original values after the call) and the callee function changes the values of the passed argument.
Your teacher is wrong. If you need to modify arrays, pass by reference is the way to go. If you don't want something modified, pass by const reference.
To prevent accidental changes, use pass-by-const-reference; that way, by default*, the passed-in array can't get changed by the called function.
* Can be overridden with const_cast.
You can pass by reference if:
you won't modify passed object
you want to modify object and don't want to keep old object untouched
When you pass something by reference, then only pointer is passed to function. If you pass whole object then you need to copy it, so it will consume more cpu and memory.
Generally speaking, objects should always be passed by reference. Otherwise a copy of the object will be generated and if the object is substantially big, this will affect performance.
Now if the method or function you are calling does not modify the object, it is a good idea to declare the function as follows:
void some_function(const some_object& o);
This will generate a compile error if you attempt to modify the object's state inside the function body.
Also it should be noted that arrays are always passed by reference.
Hold on a second.. I'm scared at how people are answering this one. Arrays, as far as I remember, are always passed by reference.
void function(int array[])
{
std::cout << array[0] << '\n';
}
// somewhere else..
int array[2] = { 1, 2 };
function(array); // No copy happens here; it is passed by reference
Further, you can't say the array argument is a reference explicitly, as that would be the syntax for creating an array of references (something that's not allowed).
void function(int &array[]) // error here
{ /* ... */ }
So what do you mean?
Further, many are saying that you should only do that if you modify the contents of the array inside the function. Then, what about reference-to-const?
void function(const int arr[])
{
std::cout << arr[0] << '\n';
}
-- edit
Will somebody please point me out how to not pass an array by reference in C++?
-- edit
Oh, so you're talking about vectors. Okay, then the rules of thumb are:
Pass by reference only when you want to modify the contents of the vector.
Pass by reference-to-const whenever you can.
Pass by value only when the object in question is really, really small (like a struct containing an integer, for example), or when it makes sense to (can't think of a case out of the top of my head).
Did I miss something?
-- edit
In the case of plain C arrays, it's a good idea to pass them by reference (like in void function(int (&array)[100])) when you want to ensure that the array has a given definite size.
Thanks, dribeas.
Usually, in introductory courses, they tell you that so you don't accidentally change something you didn't want to.
Like if you passed in userName by reference, and accidentally changed it to mrsbuxley that probably would cause errors, or at the very least be confusing later on.
I don't see any reason why you can't pass by reference. Alternatively you could pass pointers around, but I think pass by reference is better sometimes as it avoids null pointer exceptions.
If your teacher has suggested this as some kind of convention, then feel free to break it if it makes sense to. You can always document this in a comment above the function.
Our house style is to NEVER pass an object by value but to always pass a reference or const reference. Not only do we have data structures that can contain 100s of MB of data and pass by value would be an application killer, but also if we were passing 3D points and vectors by value the our applications would grind to a halt.
It is always a good choice to pass object by reference but we need to be careful and first we have to decide what is our purpose/ purpose of our function?
You have to make a choice here, whether we are gonna only read the data of an object or modify it.
Suppose you got an interface like
void increament_value(int& a);
so in this you can modify value an object which we are passing, but it is a disaster when you passing your sensitive data, you might lose you original data and can not revert it, right?
so c++ provides you a functionality to not to change the value of an object whose reference you are passing to a function, and it is always a good choice to pass a const reference of an object for e.g.,
double get_discounted_amount(const double &amount,double discount){
return (amount*discount/100);
}
This guarantees that your actual value of an object is not gonna change, but again it depends on purpose of your interface whether you wanna change it or only use(read) it