void foo(const int& v) {
int x = v;
std::cout << x;
}
int main()
{
unsigned y = 1;
foo(y);
}
Is passing y
in place of a const int&
legal in C++
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. At times, copying your parameters can also give you locality benefits.
What is one benefit of declaring the parameter as a const reference instead of declaring it as a regular object? Actually, objects cannot be passed as regular variables, because they require a constructor call. Therefore, a const reference is the only way to pass class instances to functions.
The important difference is that when passing by const reference, no new object is created. In the function body, the parameter is effectively an alias for the object passed in. Because the reference is a const reference the function body cannot directly change the value of that object.
Passing by const reference offers the same primary benefit as pass by reference (avoiding making a copy of the argument), while also guaranteeing that the function can not change the value being referenced.
There are two factors that allow your code to work. First, function arguments are allowed up to one implicit conversion if it would allow them to match an overload. Second, const
references can bind to temporaries. What is happening here is y
is implicitly converted to int
, creating a temporary copy. v
is then bound to that temporary.
Consider the following example :
#include <iostream>
void foo(const unsigned int & v) {
std::cout << &v << '\n';
}
void bar(const int & v) {
std::cout << &v << '\n';
}
int main()
{
unsigned int y = 1;
std::cout << &y << '\n';
foo(y);
bar(y);
return 0;
}
You will find that foo(y)
prints the same address as y
where as bar(y)
prints a different address. This won't work with non-const
references. Notably, if you could, it would mean that changing v
might not actually change y
.
Yes, this this can be quite annoying. Compilation passes due to an implicit conversion of y
to an anonymous temporary int
at the calling site, and a const int&
binding is allowed.
You can defeat this by writing
void foo(unsigned v) = delete;
or even
template<typename Y> void foo(Y v) = delete;
so all overloads other than the one you have explicitly given are deleted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With