练习6.11
void reset(int &i)
{
i = 99;
}
int main() {
int j = 42;
reset(j);
cout << "j = " << j << endl; //j=99
}
练习6.12
void reset(int &p, int &q)
{
int a = p;
int b = q;
p = b;
q = a;
}
int main() {
int i = 42, j = 84;
reset(i,j);
cout << "i = " << i << endl;
cout << "j = " << j << endl;
}
和指针交换差不多吧。
练习6.13
void(T),实参的初始值拷贝给变量,对变量的改动不会影响初始值。即传值调用不会改变实参。比如求阶乘的函数,fact函数中,尽管fact函数中val的值根据路径一直在改变,但是这个变动不会影响传入fact的实参,即调用fact(i)不会改变i的值。
void(&T)中的形参是引用类型,它将绑定到对应的实参上。此时改变T就是改变T所引对象的值。使用引用能够避免拷贝,比如有的类类型不支持拷贝操作的时候,就可以通过引用形参访问该类型的对象。
练习6.14
交换两个整数的值,需要用到引用,因为需要更改实参的值。如果没有用到引用,将没有发生交换:
void reset(int p, int q)
{
int a = p;
int b = q;
p = b;
q = a;
}
int main() {
int i = 42, j = 84;
reset(i,j);
cout << "i = " << i << endl;
cout << "j = " << j << endl;
}
另外,拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型根本不支持拷贝操作。当某种类型不支持拷贝操作时,函数就只能通过引用形参访问该类型的对象。
而在阶乘函数中,不需要更改实参的值,不需要用到引用。
练习6.15
函数中不需要改变引用形参 &s的值,而且要避免拷贝string,因为它的值可能很长,因此为常量引用。
而occurs的值根据字符出现次数累加,会更改,因此不可能是常量引用,是普通引用。它是引用类型的形参而不是普通形参的原因是,因为返回值只有1个,是ret。那还需要返回出现的次数的话,只能通过绑定实参,更改实参的值来实现了。
字符的话,它不需要改变它的实参,也不需要返回,所以是一个普通的形参。
s是普通引用没有问题。
occurs不能是常量引用,因为在函数体中它出现在左值的位置,左值必须是可以修改的左值,而常量不能修改,所以错误。
auto index = find_char("hello world", 'o', ctr);
但是occurs是常量引用,没法更改这个值的情况下,不能累加出现的次数。错误。
string::size_type find_char(const string& s, char c, string::size_type& occurs)
{
auto ret = s.size();
occurs = 0;
for (decltype(ret) i = 0; i != s.size();++i) {
if (s[i] == c) {
if (ret == s.size())
ret = i;
++occurs;
}
}
return ret;
}
int main() {
string s = "today";
string::size_type ctr = 0;
auto index = find_char(s, 'o', ctr);
cout << index << endl; //第一次出现的位置是1
cout << ctr << endl; //总共出现1次
}