Przemyslaw said:
Hi all,
Is there any difference between the following:
foo someFunction(const foo& A)
{
foo B(A);
// do sth. to B
return B;
}
and
foo someFunction(foo A)
{
// do sth. to A
return A;
}
I think there is none (a short test on gcc, with all
optimalizations on, seems to support this), but if
there is any I would like to know.
Semantically, there's a difference. When you pass by reference, the
compiler has to preserve the lvalue identity of the argument. For example:
1) Built-in unary '&' applied to the parameter has to return the address
of the actual argument
void foo(const int& a, const int& b) {
assert(&a == &b);
}
// The above 'assert' has to hold if called as
int i;
foo(i, i);
2) A non-constant argument can be legally modified through const
reference by using 'const_cast'
void foo(const int& a) {
const_cast<int&>(a) = 42;
}
// The above modification is legal if called as
int i;
foo(i);
assert(i == 42);
// i.e. this assertion has to hold
3) Possible aliasing
int x = 0;
void foo(const int& a) {
x = 42;
assert(a == 42);
}
// The above 'assert' has to hold if called as
foo(x);
Which means that the compiler can't simply treat const reference
parameters as being equivalent to value parameters. They are not.
Of course, a very smart compiler can recognize these situations and
stick to the strict semantics when they occur, while using const
references and copied values interchangeably in all other cases. This is
not simple though in general case.
Is any of these two forms preferable? Why?
In situations when you can use either, it might be more optimal to pass
small objects by value and large objects by reference.