I have just begun using C++, with a base in C. Having learned about Call by reference, I need to know,if in the following function I found online:
int insertSorted(int arr[], int n, int key, int capacity)
{
if (n >= capacity)
return n;
arr[n] = key;
return (n+1);
}
,which is used for insertion in an unsorted array, will the array in the main function get affected/changed? Since the arr[] argument in the function is not a reference variable, so how do any changes in this called function, reflect in the calling function? Is this correct code, if at all? I am basing my question upon the fact that call by value, creates copy variables and changes them, while call by reference changes the actual variables themselves. I'm sorry if this question is a bit silly.
Any help in clearing up this concept would be great.
Thanks.
arr is effectively a pointer to the array. Thus, in your case it acts like a reference and the function changes the array arr points to.
If you want to do it more the C++ way you should use a std::vector<int> instead of a int[] for your array. std::vector has all features of a C-style array but takes care of memory management and the actual number of elements.
In case of a std::vector you really have to pass a reference (std::vector &), otherwise the function will receive a copy of the entire array.
Related
For example, can you explain what would happen in the following code?
class Vector{
int v[3];
Vector(int *x);//parameterized constructor created
};
Vector::Vector(int *x)//definition of the parameterized constructor
{
for (int i=0;i<size;i++)
v[i]=x[i];//what happens here?? why did we take pointer as arguement?
}
From my understanding, by putting v[i]=x[i] we created a new array in which all elements of v are now in x. Why did this require a pointer argument? Couldn't it have been done with a reference &?
This goes back to older style C habits, when you can use a pointer as an array, by "indexing" it's elements.
Taken from: https://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays
A variable declared as an array of some type acts as a pointer to that type. When used by itself, it points to the first element of the array.
A pointer can be indexed like an array name.
However, a few notes:
v[i]=x[i] we created a new array
No, you did not create a new array here, the array was already created when the body of the constructor got executed. What happens here is that TO the value v[i] we will assign the value of: *(x + i) ie. the ith. element from the address x points to. Unless you know how x was created and initialized this is pretty dangerous code. Just imagine you can call this method with the address of a single int. I suppose, size is 3 or less, otherwise this code has serious security issues.
You always should check for null pointers, before trying to access the value they point to.
You can pass in the array by reference if you know the size of x at compile time:
Vector(int (&x)[3]);
If you don't know the size at compile time then what you're doing goes from being unsafe code, to blatantly wrong code.
Another option is to use std::array if you know the size at compile time, and std::vector if you don't.
Just to add a bit to previous answers, the indexing operator [] actually dereferences a pointer and shifts it by index*sizeof(type) at the same time. The same relates to declaration of an array. Say, if you declare int a[1]; this means that a is now a pointer to int, i.e. int*. So if you wanted to pass it to a function as an argument, you would need to specify its type as int*.
I understand the implicit conversion into a pointer. Someone suggested something like this today in some other question:
#include <iostream>
void printArray(int (&a)[5]) {
for (int i : a) {
std::cout << i << " ";
}
}
int main() {
int a[] = { 1, 2, 3, 4, 5 };
printArray(a);
}
Questions
Is this the only and the best way of passing an entire array to a function rather than just the pointer to the first element (though inefficient)?
However, if that function were to be written below the main function, what would the function prototype be?
Also, if I were to only use an enhanced for loop to iterate through the elements of an array passed to a function, is there any better way?
1) This does not pass the entire array to the function. It passes a reference to the array. Since the compiler knows the type of the argument, it is able to do appropriate checks (when calling the function) and access array elements (within the function).
2) The declaration of the function (as opposed to the definition/implementation) would be;
void printArray(int (&a)[5]);
The name of the parameter (a) is optional in this.
3) Since printing an object (including an array) does not typically change the object, it would be appropriate for the argument of printArray() to be const-qualified. This also allows the caller to pass a const array (which is not possible in the code as shown). Furthermore, the type of i used in the loop can also be a const reference (which avoids copying elements of the array by value). It would also be possible to use automatic type inference (i.e. auto). Increased const-safety is often viewed as beneficial (since it increases chances of picking up attempts to modify something that should not be changed).
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).
This question already has answers here:
Why doesn't C++ support functions returning arrays?
(10 answers)
Closed 10 years ago.
I've got a syntax question in C++ about returning an array. When we pass in an array, when can do like this:
void merge_sort(int input_array[], int size);//notice the first parameter
I know this works:
int* merge_sort(int input_array[], int size){
//do something with input_array
return new int[2]; //dummy array
}
Question:
int[] merge_sort(int input_array[], int size){ //Question is on return type, wont compile
//do something with input_array
return new int[2]; //dummy array
}
return int* succeed. Why returning int [] fail?
In both C and C++, you cannot either pass an array as an argument to a function, or return an array as a function result.
Yes, the syntax can make it look like you're passing an array argument:
void func(int param[]) {
// ...
}
...
int arr[10];
func(arr);
but in fact that's just passing a pointer to the array's first element. The parameter definition int param[] is adjusted; it's exactly equivalent to int *param. And an expression of array type, in most contexts, is implicitly converted to a pointer its first element.
That's why you need to pass the size as a separate argument.
Using only C features, there are several ways to do something like returning an array:
A function can return a pointer to the first element of a static array. This has some disadvantages: the size has to be fixed, and multiple callers get pointers to the same object.
A function can receive a pointer to the first element of an array, passed in by the caller. This places the burden of allocating and deallocating the array on the caller.
A function can return a pointer to the first element of a dynamically allocated (malloc() in C, new in C++) array. This requires the caller to deallocate the array.
C++ provides a rich set of library classes that can take care of all this for you.
Recommended reading: Section 6 of the comp.lang.c FAQ.
You can pass structs as arguments, and return them as function results, and structs can contain arrays as members. But that's not as useful as you might think. An array that's a member of a struct must have a fixed size; most useful code that operates on arrays can handle dynamic sizes.
Why would you want to return anything in the first place?
Array is not really "passed" to the function (no copy of the elements is made), only the pointer to it's beginning is. When the function rearranges the array elements, it is doing so in the original array. After the function exits, the calling code can simply continue to use the old (now-sorted) array.
In other words, the function produces a side-effect.
I know this works:
int* merge_sort(int input_array[], int size){
//do something with input_array
return new int[2]; //dummy array
}
(Assuming you actually need to return...)
Well it "works", but is very dangerous. The caller needs to be aware it needs to free the returned array (otherwise a memory leak ensues), and it needs to be aware it must use delete[] and not just delete (otherwise an undefined behavior ensues), which is distinctly non-obvious based only on the return type (which is just a pointer). The caller might also be in doubt whether the input_array is freed inside the function or not.
Even if you have documented all that, it's extremely easy for the caller to make a mistake. It's much better to use the facilities provided by modern C++ instead: for example, you could return an std::vector.
you should be using a vector in this approach, in your project include and then use a vector almost as u would with an array.
u can have a look at vectors here: http://msdn.microsoft.com/en-us/library/vstudio/9xd04bzs.aspx
the great thing about vectors is that they are dynamically scaling for your projects and would not create any memory leaks or such due to buffer overflow's, its much like an ArrayList
void revalue(int r, int ar[], int n)
{
for(int i=0; i<n;i++)
{
ar[i]*=r;
}
}
So I'm really confused with how this code works and why it changes the ar[]. The thing is I thought that everytime you pass variables that aren't reference or pointers into a function a copy of the variable is made, then the copy is deleted after it goes out of scope of the function. Yet this function changes the array values.
How is this possible?
Pretty simple really: when you use array notation for a parameter in C or C++, it's silently adjusted by the compiler to actually pass a pointer.
IOW, your function is really:
void revalue(int r, int *ar, int n)
...and from there, most of it is pretty clear.
I guess, the confusion is with int ar[] which, in this context, is equivalent to writing int* ar: In C++ you cannot pass built-in arrays by value. However, they easily decay into pointers and the above is an alternative notation. Note that you could have used int ar[10] or int ar[20] and it would have been identical, too.
Arrays are passed by reference by default in c++ being adjusted to a pointer to the first element of the array.