After years of AS3, I'm trying to relearn C++. References are still giving me fits.
Consider the following functions:
#include <cstdio>
#include <list>
void f(std::list<int>& v) {
for (std::list<int>::iterator i = v.begin(); i != v.end(); ++i)
printf("Hello %d\n", *i);
}
std::list<int> get(void) {
std::list<int> list;
list.push_back(0);
return list;
}
Now, doing the following:
std::list<int> l = get();
f(l);
is fine, but f(get())
will produce the following error:
"no matching function for call to 'f'", "candidate function not viable: no known conversion from `'std::list<int>' to 'std::list<int>&' for 1st argument"
Why is that? Is it because the result of a function is invisibly const
?
When a function is called, the arguments in a function can be passed by value or passed by reference. Callee is a function called by another and the caller is a function that calls another function (the callee). The values that are passed in the function call are called the actual parameters.
Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in.
To pass a value by reference, argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to, by their arguments.
In C++, variables are passed by reference due to following reasons: 1) To modify local variables of the caller function: A reference (or pointer) allows called function to modify a local variable of the caller function.
When you do this:
f(get());
you pass a temporary std::list<int>
to f()
. A temporary cannot bind to a non-const reference. So you can fix this by passing a const
reference, since you do not want to modify the argument.
void f(const std::list<int>& v)
{ // ^^^^^
for (std::list<int>::const_iterator i = v.begin(); i != v.end(); ++i)
{ // ^^^^^^^^^^^^^^
printf("Hello %d\n", *i);
}
}
Note that this requires that you use a const_iterator
, since std::list::begin() const
and the corresponding end()
method return const_iterator
s. In C++11 you can simplify this to
for (auto i = v.begin(); i != v.end(); ++i)
...
or even
for (const auto& i : v)
std::cout << i << "\n";
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