Newbie here, I am reading some code, and I see sometimes the author used the reference in a function as
funca (scalar& a)
// Etc
Sometimes he just use
funcb (scalar a)
// Etc
What's the difference? Is using a reference a good habit that I should have?
Thank you!
If you call foo(scalar a), the argument a of type scalar will be COPIED from the caller and foo will have it's own COPY of the original object.
If you call foo(scalar &b), the argument b will be just a reference to the original object, so you will be able to modify it.
It's faster to pass an object by reference using the &name syntax, since it avoids creating a copy of the given object, but it can be potentially dangerous and sometimes the behavior is unwanted because you simply want an actual copy.
That being said, there's actually an option that disallows the ability to modify the original object for the called function yet avoids creating a copy. It's foo(const scalar &x) which explicitly states that the caller does not want the function foo to modify the object passed as an argument.
Optional reading, carefully:
There's also a way of passing an argument as a raw pointer which is very rare in modern C++. Use with caution: foo(scalar *a). The caller has got to provide the address of an object instead of the object itself in this scenario, so the caller would call foo(&a). For the called function foo to be able to modify the object itself in this case, it would need to dereference the pointer a, like this in foo: *a =. The star in front of the variable name in this case says that we don't want to modify the address that we have received (as a direct result of the calling function providing &a, that is, the address of the object a).
Passing a parameter by reference allows the called function to modify its argument in a way that will be visible to the caller after the function returns, while passing by value means that any changes will be limited in scope to the called function. Therefore passing by (non-const) reference typically signifies that the callee intends to modify the argument or, less commonly, use it as an additional "return value".
Additionally, passing by reference means that no copy of the parameter needs to be made; passing by value requires such a copy (which may be detrimental for the memory footprint or runtime performance of your application). For this reason you will often see arguments of class type being passed as a const reference: the callee does not intend to modify the argument but it also wants to avoid a copy being made. Scalar arguments are of very small size, so they do not benefit from this approach.
See also Pass by Reference / Value in C++.
Call by value (funcb (scalar a)) will give the function a copy of the argument, so changes made to the argument are not visible to the caller.
Call by reference (funcb(scalar& b)) means that the function operates directly on the argument, so any changes made are directly visible to the caller.
Whether or not call by reference is a good practice depends on the circumstances. If you need the function to modify the argument (and the modifications to be visible to the caller) you obviously want to use call by reference. If you don't want to modify the argument using non-const reference arguments is misleading (since the signature indicates the argument could be changed), so call by value is more apropriate here. Of course for more complex types call by value can have a non-trivial overhead. In these cases call-by-const-reference is preferable (funcc(const scalar& c))
Related
From what I understand: when you pass by value, the function makes a local copy of the passed argument and uses that; when the function ends, it goes out of scope. When you pass by const reference, the function uses a reference to the passed argument that can't be modified. I don't understand, however, why one would choose one over the other, except in a situation where an argument needs to be modified and returned. If you had a void function where nothing is getting returned, why choose one over the other?
EDIT: So basically passing by const reference avoids copying the object. So in what situations is copying the object good? I mean, why not just use const references all the time if it optimizes performance all the time?
There are two main considerations. One is the expense of copying the passed object and the second is the assumptions that the compiler can make when the object is a a local object.
E.g. In the first form, in the body of f it cannot be assumed that a and b don't reference the same object; so the value of a must be re-read after any write to b, just in case. In the second form, a cannot be changed via a write to b, as it is local to the function, so these re-reads are unnecessary.
void f(const Obj& a, Obj& b)
{
// a and b could reference the same object
}
void f(Obj a, Obj& b)
{
// a is local, b cannot be a reference to a
}
E.g.: In the first example, the compiler may be able to assume that the value of a local object doesn't change when an unrelated call is made. Without information about h, the compiler may not know whether an object that that function has a reference to (via a reference parameter) isn't changed by h. For example, that object might be part of a global state which is modified by h.
void g(const Obj& a)
{
// ...
h(); // the value of a might change
// ...
}
void g(Obj a)
{
// ...
h(); // the value of a is unlikely to change
// ...
}
Unfortunately, this example isn't cast iron. It is possible to write a class that, say, adds a pointer to itself to a global state object in its constructor, so that even a local object of class type might be altered by a global function call. Despite this, there are still potentially more opportunities for valid optimizations for local objects as they can't be aliased directly by references passed in, or other pre-existing objects.
Passing a parameter by const reference should be chosen where the semantics of references are actually required, or as a performance improvement only if the cost of potential aliasing would be outweighed by the expense of copying the parameter.
Passing arguments by value and thus copying them can be expensive - const references avoid that expensive step while still promising the caller that the object won't be changed.
Usually fundamental types (int, double, ...) are passed by value, while class-types are passed by const reference.
There can however be exceptions where pass-by-value for class-types can be beneficial.
Making a copy of an object could greatly affect the performance in some cases. Consider a function which argument will be std::vector<long> and you want to pass vector with 1 million elements. In this case you'll want to use const reference over passing by value. In this SO question you could find simple general rule for your question.
Sometimes, making a copy of an object can be expensive and so pass-by-const-reference will avoid having to make that copy. Otherwise, I would say that you should simply pass-by-value if that is what is semantically required.
To avoid making an unnecessary copy, thus improving performance.
Passing an argument by value has the overhead of a copy of the object being passed to the function.
Maybe an object isn't copyable and your choices are limited.
Because of the performance benefits you will get. Lets say you have a big object (in terms of size in bytes). Now, if you pass this object by value to a function a unnecessary copy needs to be created of this, however you can get the same effect by passing a const reference to that object itself without creating copy. Since a reference is normally stored as a pointer under the hoods, the cost of passing a reference is just sizeof(pointer).
An array can't be passed by value, so this is a good time to use a const pointer.
In what circumstances should I prefer pass-by-reference? Pass-by-value?
There are four main cases where you should use pass-by-reference over pass-by-value:
If you are calling a function that needs to modify its arguments, use pass-by-reference or pass-by-pointer. Otherwise, you’ll get a copy of the argument.
If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.
If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.
There are several considerations, including:
Performance
Passing by value copies the data, so passing large data structures by value can inhibit performance. Passing by reference passes only a reference (basically the address) to the data. For large data structures, this can greatly improve performance. For smaller data structures (like an int), passing by reference can inhibit performance.
Modifications
Passing by value copies the data so if the target code modifies that copy, it will not affect the original. Passing by reference passes only the address of the data, so modifications made against that reference will be "visible" to the calling code.
Yes.
Pass by value for things like native types that are small enough that passing them directly is efficient. Otherwise use pass by (const) reference.
The hard part is writing a template that could apply to either (in which case, you usually want to use pass by reference -- the potential penalty for passing a large object by value is much worse than the potential penalty for passing by reference when passing by value would have been preferred).
Edit: this, of course, is assuming a situation where the required semantics would allow either one -- obviously if you're working with something like polymorphic objects, there's no real "preference" involved, because you must use a pointer or reference to get correct behavior.
As others already have replied to your question sufficiently well, I would like to add an important point:
If the class does not have public copy-constructor, then you don't have choice to pass by value; you have to pass by reference (or you can pass pointer).
The following program would not compile:
class A
{
public:
A(){}
private:
A(const A&) {}
};
//source of error : pass by value
void f(A ) {}
int main() {
A a;
f(a);
return 0;
}
Error:
prog.cpp: In function ‘int main()’:
prog.cpp:10: error: ‘A::A(const A&)’ is private
prog.cpp:18: error: within this context
prog.cpp:18: error: initializing argument 1 of ‘void f(A)’
See yourself at ideone : http://www.ideone.com/b2WLi
But once you make function f pass by reference, then it compiles fine : http://www.ideone.com/i6XXB
here's the simple rule:
pass by reference when the value is large.
the other answers are amazing. Just trying to make this simplest.
You have tagged your question with both C and C++.
Therefore, I suggest that you consider using pass by reference in C++ which supports this feature and that you do not consider using it in C which does not support this feature.
pass by reference can be called only in below conditions:
Pass-by-references is more efficient than pass-by-value, because it does not copy the arguments. The formal parameter is an alias for the argument. When the called function read or write the formal parameter, it is actually read or write the argument itself.
The difference between pass-by-reference and pass-by-value is that modifications made to arguments passed in by reference in the called function have effect in the calling function, whereas modifications made to arguments passed in by value in the called function can not affect the calling function.
Use pass-by-reference if you want to modify the argument value in the calling function. Otherwise, use pass-by-value to pass arguments.
The difference between pass-by-reference and pass-by-pointer is
that pointers can be NULL or reassigned whereas references cannot.
Use pass-by-pointer if NULL is a valid parameter value or if you want to reassign the pointer.
Otherwise, use constant or non-constant references to pass arguments.
While pointers are references, "reference" in c++ usually refers to the practice of tagging a parameter of SomeType&.
Which you should never do. The only place it is appropriate is as a magic syntax required to implement the various pre-defined operators. Otherwise:
You should never pass out parameters by reference - pass by pointer, otherwise you make code reviews all but impossible. Pass by reference makes it impossible to tell by examining a call which parameters can be expected to be changed.
You should never pass in parameter by reference either. Again, this means you are performing a meta optimization. You should always just pass-by-value, otherwise you are guilty of peeking inside an object, examining its implementation and deciding that pass-by-reference is preferred for some reason.
Any c++ class should implement all the copy and assignment constructors and overloads necessary to be passed around by value. Otherwise it has not done its job, of abstracting the programmer from the implementation details of the class.
I am a little confused about the differences between call by value and const call by reference. Could someone please explain this to me. For example, do they both protect against changing the callers argument, are they fast for all object sizes, do either copy the argument while one doesnt, and which use more memory when making a copy?
do they both protect against changing the callers argument
Passing by value creates a copy of the argument provided by the caller, so whatever the function does, it does it on a separate objects. This means the original object won't ever be touched, so in this case the answer is "Yes".
Passing by reference to const, on the other hand, lets the function refer the very same object that the caller provided, but it won't let that function modify it... Unless (as correctly remarked by Luchian Grigore in the comments) the function's implementer uses const_cast<> to cast away the const-ness from the reference, which is something that can be safely done only if it is known that the object bound to the reference was not declared to be of a const type (otherwise, you would get Undefined Behavior).
Since this does not seem to be the most likely scenario considering your question, and considering that in general accepting a reference to const represents a promise that the argument won't be touched, then the answer is that as long as we assume this promise to be fulfilled, passing by reference to const won't alter the argument provided by the caller. So the answer is "Yes" again - with the little caveat I mentioned above.
are they fast for all object sizes
No. Although you should first define "fast". If the type of the object being passed is expensive to copy (or to move, if a move is performed rather than a copy), then passing by value might be slow. Passing by reference will always cost you the same (the size of an address), no matter what is the type of the value you are passing.
Notice, that on some architecture and for some data types (like char) passing by value could be faster than passing by reference, while the opposite is generally true for large enough UDTs.
and which use more memory when making a copy?
Since only one of them is causing a copy, the question has an obvious answer.
The main difference is that passing by const reference (or non-const) doesn't make a copy of the argument. (the copy is actually subject to copy elision, but theoretically it's a copy that's passed to the function when you pass by value)
In some cases, passing by value is just as fast, or even faster (typically when the object is at most the size of a register). You'd usually pass basic types by value, and class-types by reference.
When passing by const reference you can still modify the original value just by casting the const away (via const_cast), but that results in undefined behavior if the original value is const.
call by value will copy all the elements of the object it does protect the callers argument because if you are going to change something it is only a copy you are changing.
calling by const reference does not copy elements but because of the "const" it will protect caller's argument.
You const reference.
I suppose that you mean the difference between:
void Fn1(MyType x);
and
void Fn2(const MyType& x);
In former case, a copy of the object is always created, which makes it slower especially if the type has a non-trivial constructor. The original object will be unaffected by any changes done on the copy within the function, but the copy itself can be changed.
The latter example will not create a copy and will in general be faster. Inside the function, only the const functions can be called on the argument (unless you resort to dirty tricks like casting away constness), thus guaranteeing that the object will not be modified.
IMPORTANT: This discussion doesn't cover types with special semantics, like smart pointers. In that case, call by value will still allow you to change what is logically the same object, i.e. not the smart ptr instance itself but the object it points to.
So here are the answers to your questions:
do they both protect against changing the callers argument: yes, the original object will remain unchanged (excluding tricks)
are they fast for all object sizes: they are not equally fast - call by reference is in general faster, except for some primitive types where speed is more or less the same or maybe even marginally faster, depending on compiler optimizations.
do either copy the argument while one doesnt: call by value creates a copy, call by reference doesn't
which use more memory when making a copy? call by reference doesn't create a copy so the answer is clear
One other point worth mentioning is that call-by-reference functions are converted into inline functions.
Can some body tell me the reason why we usually put const and & with some object which is passed in the constructor for example.
Book::Book(const Date &date);
The confusion that i have here is that usually & sign is used in the some function because the value is passed by reference and whatever changes happen to that variable in the function should reflect afterwards. But on the other hand const says that no assignment can be done to that variable.
If some body have some good idea about that please let me know the reason for that.
This is done to avoid an unnecessary copy. Take, for example, the following code:
Book::Book(Date date):
date_(date)
{
}
When you call this constructor it will copy date twice, once when you call the constructor, and once when you copy it into your member variable.
If you do this:
Book::Book(const Date &date):
date_(date)
{
}
date is only copied once. It is essentially just an optimisation.
The most common alternative is to pass by value:
Book::Book(Date date);
Passing by const reference prevents the parameter date from being copied when the parameter you pass is already a Date. Copying objects can be unnecessary, can be costly to perform, or it could result in a sliced object (and the incorrect results).
'Slicing' is basically demotion of an object's type via copy to its base. For a polymorphic type, this can actually change its behavior because the parameter would be copied as its base (Date), and then calls to its polymorphic interfaces would be different because the implementation has changed (e.g. its virtual methods would use the base's implementation instead).
It means that you pass the object via refrence (as you noted), but the object itself cannot be changed from the function (ctor in this case).
The reason for this could be:
you do not want to copy the full object, to make your code more efficient
you do not want to accidentially change the passed-in object
you want to be able to use the function with unnamed temporaries
you want to be able to pass objects that derive from the noted type (Date in this case)
For the third point, consider:
Book b(Date());
It's typically a performance optimization for input parameters. If you omit the '&' the parameter is accepted by value and the input object will have to be copied before being passed to the function. Passing by reference bypasses the copy.
In c++, when you have a parameter type of a function be something like const Type&, what you are doing is allowing a user to pass some value in by reference - A pointer to the value is implicitly passed in, but for ease of use, the compiler allows you to treat it as if it was a value.
In some cases, the compiler can also optimize it so that no pointer is used at all, and the function can refer directly to the memory of the value.
The reason that const is used is to safeguard yourself from altering memory that the user doesn't expect you to alter, and also to have it still work if the user passes in a const variable.
A const reference is a way of passing the data to the class without copying the data to a local copy, and still guaranteeing that the original object won't be modified by the function.
In what circumstances should I prefer pass-by-reference? Pass-by-value?
There are four main cases where you should use pass-by-reference over pass-by-value:
If you are calling a function that needs to modify its arguments, use pass-by-reference or pass-by-pointer. Otherwise, you’ll get a copy of the argument.
If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.
If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.
There are several considerations, including:
Performance
Passing by value copies the data, so passing large data structures by value can inhibit performance. Passing by reference passes only a reference (basically the address) to the data. For large data structures, this can greatly improve performance. For smaller data structures (like an int), passing by reference can inhibit performance.
Modifications
Passing by value copies the data so if the target code modifies that copy, it will not affect the original. Passing by reference passes only the address of the data, so modifications made against that reference will be "visible" to the calling code.
Yes.
Pass by value for things like native types that are small enough that passing them directly is efficient. Otherwise use pass by (const) reference.
The hard part is writing a template that could apply to either (in which case, you usually want to use pass by reference -- the potential penalty for passing a large object by value is much worse than the potential penalty for passing by reference when passing by value would have been preferred).
Edit: this, of course, is assuming a situation where the required semantics would allow either one -- obviously if you're working with something like polymorphic objects, there's no real "preference" involved, because you must use a pointer or reference to get correct behavior.
As others already have replied to your question sufficiently well, I would like to add an important point:
If the class does not have public copy-constructor, then you don't have choice to pass by value; you have to pass by reference (or you can pass pointer).
The following program would not compile:
class A
{
public:
A(){}
private:
A(const A&) {}
};
//source of error : pass by value
void f(A ) {}
int main() {
A a;
f(a);
return 0;
}
Error:
prog.cpp: In function ‘int main()’:
prog.cpp:10: error: ‘A::A(const A&)’ is private
prog.cpp:18: error: within this context
prog.cpp:18: error: initializing argument 1 of ‘void f(A)’
See yourself at ideone : http://www.ideone.com/b2WLi
But once you make function f pass by reference, then it compiles fine : http://www.ideone.com/i6XXB
here's the simple rule:
pass by reference when the value is large.
the other answers are amazing. Just trying to make this simplest.
You have tagged your question with both C and C++.
Therefore, I suggest that you consider using pass by reference in C++ which supports this feature and that you do not consider using it in C which does not support this feature.
pass by reference can be called only in below conditions:
Pass-by-references is more efficient than pass-by-value, because it does not copy the arguments. The formal parameter is an alias for the argument. When the called function read or write the formal parameter, it is actually read or write the argument itself.
The difference between pass-by-reference and pass-by-value is that modifications made to arguments passed in by reference in the called function have effect in the calling function, whereas modifications made to arguments passed in by value in the called function can not affect the calling function.
Use pass-by-reference if you want to modify the argument value in the calling function. Otherwise, use pass-by-value to pass arguments.
The difference between pass-by-reference and pass-by-pointer is
that pointers can be NULL or reassigned whereas references cannot.
Use pass-by-pointer if NULL is a valid parameter value or if you want to reassign the pointer.
Otherwise, use constant or non-constant references to pass arguments.
While pointers are references, "reference" in c++ usually refers to the practice of tagging a parameter of SomeType&.
Which you should never do. The only place it is appropriate is as a magic syntax required to implement the various pre-defined operators. Otherwise:
You should never pass out parameters by reference - pass by pointer, otherwise you make code reviews all but impossible. Pass by reference makes it impossible to tell by examining a call which parameters can be expected to be changed.
You should never pass in parameter by reference either. Again, this means you are performing a meta optimization. You should always just pass-by-value, otherwise you are guilty of peeking inside an object, examining its implementation and deciding that pass-by-reference is preferred for some reason.
Any c++ class should implement all the copy and assignment constructors and overloads necessary to be passed around by value. Otherwise it has not done its job, of abstracting the programmer from the implementation details of the class.