I read that they are conceptually equal. In practice, is there any occasion that
foo(T t)
is preferred over
foo(const T& t)
? and why?
Thanks for the answers so far, please note I am not asking the difference between by-ref and by-val.
Actually I was interested in the difference between by-const-ref and by-val.
I used to hold the oipinion that by-const-ref can replace by-value in call cases since even Herb Sutter and Bjarne said they are conceptually equal, and "by ref"(be it const) implies being faster. until recently, I read somewhere that by-val may be better optimized in some cases.
Then when and how?
Boost.CallTraits is a lesser-known but helpful facility for doing parameter and result passing with what should be the most efficient method available for the type in question.
Here is a case when you don't have other option but only to pass a parameter by value. Of course boost does handle this. But without boost we have to pass a Value to function by value.
Some routines require a copy, and so should not be pass by reference. For example, a chess playing program's move generator might need a copy of the current position to work on (recursively) rather than actually modifying the original instance of the position.
Answered in this answer. This is a SymLink to that answer. Please vote there, if anywhere :)
If the object being passed is a smart pointer (i.e. it does its own reference counting) then passing by value might be more reasonable.
I realize that's sort of a sideways answer to your question - the object wrapped by the smart pointer is not copied when passed by value, so it's more similar to passing by reference in that case. Nevertheless, you don't need "by reference" semantics in this case.
There is a problem with my line of reasoning so far, though - you'll lose the "const-ness" of the argument by passing by value. Perhaps you should just use the "by reference" semantics after all...
Another case that hasn't been mentioned is heavy use of the object. Let's say you pass a struct with 5 ints as members. If you are going to be accessing all 5 quite a lot in your function, there comes a point when the dereference cost outweighs the copy cost. However, you'd have to run a profiler to know when that is.
I should point out, though, that things like STL containers, which allocate memory on the heap, should almost never be passed by value if avoidable, because heap allocation is very slow compared to stack allocation.