In some comp-sci papers and tests, I see swap() implemented like so:
void swap(int x, int y, int *a)
{
int t = a[x];
a[x] = a[y];
a[y] = t;
}
Why not simply implement it like so:
void swap(int& x, int& y)
{
int t = x;
x = y;
y = t;
}
Is the idea to the former to make the calling code cleaner, by not having to index into the array for the first two arguments? I realize it's not a very important question, since we should be using std::swap(), but I'm still curious.
Not all programming languages support calling by reference. For instance, the latter way of doing swap doesn't apply to Java.
In books containing pseudo-code, usually there's a convention that arrays and pointers are not copied when passed and everything else is copied in a function call. The former way requires no special explanation about the way arguments are passed.
Regarding your final point about cleanliness, it's not so much different: in the former case, your call to swap would be simply: swap(i, j, a); whereas in the latter, you'll have to swap(a[i], a[j]);, introducing some brackets in the expression.
Your second code sample is C++, NOT C. C++ supports reference parameters, but C only supports reference indirectly via pointers.
I agree that the second implementation is cleaner. In order to make it work in C, change the & in each of the parameters to * and dereference each x and y (also with *) inside the function.
Related
I was reading "Beginning C++ Through Game Programming, Fourth Edition" when I found a section about to pass a reference as an argument in a function that says:
"Pass a reference only when you want to alter the value
of the argument variable. However, you should try to avoid changing
argument variables whenever possible."
Basically it says that I shoud avoid to do something like this:
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
But, why should I avoid doing this?
I found very useful to create functions to change variables, because these functions keep my code organized avoiding me to write every variable change in the main() function, and they also avoid me to write the same code repeatedly.
What alternative is there if I should not do this?
With the case of swap, pass by reference shoud be used, because multiple variables are being changed in the function and the expected behavior of the function is obvious. If you were only changing one variable or have a function that should be returning a result, then it is better to return a value for the most part (With some exceptions). For example, supoose you had a function sum():
int sum(int a, int b)
{
return a + b;
}
Usage of this function might be:
int x = sum(1, 2); // Obvious and to the point
Since there is no need to change any of the variables, one would use pass by value here (Pass by const reference doesn't matter here, since POD types are pretty small). If you used pass by reference here, then the function would have changed to:
void sum(int a, int b, int& sum)
{
sum = a + b;
}
Usage of the function above might be:
int s;
sum(1, 2, s); // Obscure, unclear
Disadvantages of this are that it is unclear what the intent of the function is, and now the result of the function cannot be passed to another function in one line. So pass by reference should only be used when absolutely necessary.
On a side note, using a const reference for passing large objects to functions is always recommended, since it avoids a copy.
How to create simple immutable int in C++? I have a function:
int NOD(const int &a, const int &b) {
if (b == 0) {return a;}
const int remainder = a % b;
return NOD(b, remainder);
}
which supposed to take two ints and returns greatest common divisor. But I didn't find a way to make a and b immutable, hence they can be altered within function, for example if we add a line in function:
*(int *)&a = 555;
it breaks everything. How to make immutable variables in C++?
You are talking about integers. Just copy them by leaving out the reference notation and all possible changes to a and b are local to the NOD function. There are two usual reasons to use a reference. One, you wish to change them (but you don't need to here). Second, sometimes a reference offers more performance than a copy. But that's not the case here because integers are about as cheap as things get in C/C++.
int NOD(int a, int b) {
if (b == 0) {return a;}
const int remainder = a % b;
return NOD(b, remainder);
}
Your code is invoking Undefined Behavior, after which everything is possible. So, what you're asking is flat out impossible - after UB, even immutable variables are mutable.
You can never prohibit that a piece of code changes its local copy of a primitive data type, that should be clear. And this would be the same in a functional language too.
The C++ way could be to wrap the int into a class that has only one constructor taking an int and only const methods to read the content.
If you make this single constructor inaccessible to "others" than they will not be able to build a changed object on their own.
Or you could return a lambda expression, that returns the int. Internally the compiler would produce an instance of a class on the fly. Performancewise this should be about the same but maybe less clumsy to read.
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.
If I have a C++ function declaration:
int func(const vector<int> a)
Would it always be beneficial to replace it with
int func(const vector<int> &a)
since the latter does not need to make a copy of a to pass into the function?
In general, yes. You should always pass large objects by reference (or pass a pointer to them, especially if you are using C).
In terms of efficiency like you're thinking, almost always yes. There are times where (purportedly) this may be slower, typically with types that are fundamental or small:
// copy x? fits in register: fast
void foo(const int x);
// reference x? requires dereferencing on typical implementations: slow
void foo(const int& x);
But with inlining this doesn't matter anyway, plus you can just type it by-value yourself; this only matters with generic template functions.
However it's important to note that your transformation may not always be valid, namely because your function gets its own copy of the data. Consider this simpler example:
void foo(const int x, int& y)
{
y += x;
y += x;
}
int v = 1;
foo(v, v); // results in v == 3
Make your transformation and you get:
void foo(const int& x, int& y)
{
y += x;
y += x;
}
int v = 1;
foo(v, v); // results in v == 4
Because even though you cannot write to x, it can be written to through other means. This is called aliasing. While probably not a concern with the example you've given (though global variables could still alias!), just be wary of the difference in principle.
Lastly, if you're going to make your own copy anyway, just do it in the parameter list; the compiler can optimize that for you, especially with C++11's rvalue references/move semantics.
Mostly it would be more efficient -- but if it happens that func needs to make its own copy of the vector and modify it destructively while it does whatever it does anyway, then you might as well save a few lines and let the language make the copy for you implicitly as a pass-by-value parameter. It is conceivable that the compiler might then be able to figure out that the copying can be omitted if the caller is not actually using its copy of the vector afterwards.
In short, yes. Since you can't modify a anyway, all your function body could do is make another copy, which you can just as well make from a const-reference.
Some reasons I can imagine the pass by value could be more efficient:
It can be better paralellized. Because there's no aliasing. The original can change without affecting the value inside the function.
Better cache locality
Correct. Passing a reference will avoid a copy. You should make use of references when there's a copy involved and you don't actually need one. (Either because you don't intent to modify the value, in which case operating on the original is fine and you'd use a const reference, or because you do want to modify the original rather than a copy of it, in which case you'd use a non-const reference.)
This isn't limited to function arguments of course. For example, look at this function:
std::string foo();
Most people would use that function in this way:
std::string result = foo();
However, if you're not modifying result, this is way better:
const std::string& result = foo();
No copy is being made. Also, contrary to pointers, a reference guarantees that the temporary returned by foo() stays valid and will not go out of scope (a pointer to a temporary is dangerous, while a reference to a temporary is perfectly safe.)
The C++-11 standard solves this problem by using move semantics, but most existing code doesn't make use of this new feature yet, so using references wherever possible is a good habit to get into.
Also, note that you have to be careful about temporary lifetimes when binding temporaries to references, e.g.:
const int& f(const int& x)
{ return x; }
const int& y = f(23);
int z = y; /* OOPS */
The point being that the lifetime of the temporary int with value 23 doesn't extend beyond the end of the expression binding f(23) to y, so the attempt to assign y to z results in undefined behavior (due to the dangling reference).
Note that when you're dealing with POD types (Plain Old Data), like int or char, you don't win anything by avoiding a copy. Usually a reference is just as big as an int or long int (usually as big as a pointer), so copying an int by reference is the same as copying the int itself.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
Are there benefits of passing by pointer over passing by reference in C++?
In both cases, I achieved the result.
So when is one preferred over the other? What are the reasons we use one over the other?
#include <iostream>
using namespace std;
void swap(int* x, int* y)
{
int z = *x;
*x=*y;
*y=z;
}
void swap(int& x, int& y)
{
int z = x;
x=y;
y=z;
}
int main()
{
int a = 45;
int b = 35;
cout<<"Before Swap\n";
cout<<"a="<<a<<" b="<<b<<"\n";
swap(&a,&b);
cout<<"After Swap with pass by pointer\n";
cout<<"a="<<a<<" b="<<b<<"\n";
swap(a,b);
cout<<"After Swap with pass by reference\n";
cout<<"a="<<a<<" b="<<b<<"\n";
}
Output
Before Swap
a=45 b=35
After Swap with pass by pointer
a=35 b=45
After Swap with pass by reference
a=45 b=35
A reference is semantically the following:
T& <=> *(T * const)
const T& <=> *(T const * const)
T&& <=> [no C equivalent] (C++11)
As with other answers, the following from the C++ FAQ is the one-line answer: references when possible, pointers when needed.
An advantage over pointers is that you need explicit casting in order to pass NULL.
It's still possible, though.
Of the compilers I've tested, none emit a warning for the following:
int* p() {
return 0;
}
void x(int& y) {
y = 1;
}
int main() {
x(*p());
}
In fact, most compilers emit the same code for both functions calls, because references are generally implemented using pointers.
Following this logic, when an argument of (non-const) reference type is used in the function body, the generated code will just silently operate on the address of the argument and it will dereference it. In addition, when a call to such a function is encountered, the compiler will generate code that passes the address of the arguments instead of copying their value.
Basically, references and pointers are not very different from an implementation point of view, the main (and very important) difference is in the philosophy: a reference is the object itself, just with a different name.
References have a couple more advantages compared to pointers (e. g. they can't be NULL, so they are safer to use). Consequently, if you can use C++, then passing by reference is generally considered more elegant and it should be preferred. However, in C, there's no passing by reference, so if you want to write C code (or, horribile dictu, code that compiles with both a C and a C++ compiler, albeit that's not a good idea), you'll have to restrict yourself to using pointers.
Pass by pointer is the only way you could pass "by reference" in C, so you still see it used quite a bit.
The NULL pointer is a handy convention for saying a parameter is unused or not valid, so use a pointer in that case.
References can't be updated once they're set, so use a pointer if you ever need to reassign it.
Prefer a reference in every case where there isn't a good reason not to. Make it const if you can.
Here is a good article on the matter - "Use references when you can, and pointers when you have to."
Use references all the time and pointers only when you have to refer to NULL which reference cannot refer.
See this FAQ :
http://www.parashift.com/c++-faq-lite/references.html#faq-8.6