参数传递(reference parameter)
Programmers who come to C++ from a C background are used to passing pointers to obtain access to the argument. In C++ it, is safer and more natural to use reference parameters.
It should be obvious that a function that takes a plain, nonconst reference may not be called on behalf of a const object. After all, the function might change the object it is passed and thus violate the const ness of the argument. What may be less obvisous is that we also cannot call such a function with an rvalue or with an object of a type that requires a conversion:
// function takes a non-const reference parameter int incr(int &val) { return ++val; } int main() { short v1 = 0; const int v2 = 42; int v3 = incr(v1); // error: v1 is not an int v3 = incr(v2); // error: v2 is const v3 = incr(0); // error: literals are not lvalues v3 = incr(v1 + v2); // error: addition doesn't yield an lvalue int v4 = incr(v3); // ok: v3 is a non const object type int }
Parameters that do not change the value of the corresponding argument should be const references.
// returns index of first occurrence of c in s or s.size() if c isn't in s // Note: s doesn't change, so it should be a reference to const string::size_type find_char(string &s, char c) { string::size_type i = 0; while (i != s.size() && s[i] != c) ++i; // not found, look at next character return i; }
This function takes its string argument as a plain (nonconst) reference, even though it doesn't modify that parameter. One problem with this definition is that we cannot call it on a character string literal:
if (find_char("Hello World", 'o')) // ...
Best practices:Reference parameters that are not changed should be references to const . Plain, nonconst reference parameters are less flexible. Such parameters may not be initialized by const objects, or by arguments that are literals or expressions that yield rvalues.
int *&v1; // v1 is a reference to a pointer to an object of type int .
In order to avoid copying the vector , we might think that we'd make the parameter a reference. In practice, C++ programmers tend to pass containers by passing iterators to the elements we want to process:
// pass iterators to the first and one past the last element to print void print(vector<int>::const_iterator beg, vector<int>::const_iterator end) { while (beg != end) { cout << *beg++; if (beg != end) cout << " "; // no space after last element } cout << endl; }