C++ Primer学习笔记(6)—— 巧用引用形参
2015-07-04 11:08
399 查看
你是否遇到过这样的问题?写一个函数,实现两个数的交换。想当然的会写下面这样的函数:
结果是这样的:
并没有改变?!为什么呢?
其实,这里要区分函数的形参和实参。形参是在函数定义过程中定义的,在函数的形参列表中,必须标明参数的类型,是一个变量;实参是在函数调用过程中的,是一个表达式,用来给形参初始化的。
但是,要注意的是,传递的实参并不是对象本身,而是对象的副本,相当于是复制过来的。
所以问题的关键就在这里,上面传递s1, s2实参只是个副本,所以函数改变的只是副本,并没有改变s1,s2本身。
那么,怎么解决这个问题呢?
引用形参!!
把形参改成这样就可以了:
这次的运行结果为:
原因是:引用实际是对象的别名,就像我们的小名儿,代表的是我们本身,而不是我们的克隆(副本)。所以,用引用作为形参,就直接代表对象本身,不是复制来的。函数改变的就是对象本身了。
总结一下:什么情况下使用引用形参呢?
牢记以下四种情况:
需要通过函数调用改变参数对象的时候,如上面的例子;
需要通过一次函数调用获得多个结果值;
在想函数传递大型对象时,复制实参会降低效率,这时可以用引用形参;
如果实参是类类型,且其构造函数为private类型,无法复制,这时只能使用引用形参了。
关于第二点有点难以理解,举例说明一下:
例如,定义一个fing_val函数,在一个整型vector对象的元素中搜索某个特定值,该值可能出现多次。请返回一个迭代器指向该值第一次出现的位置(1),以及出现的次数(2)。
所以需要返回两个值。而一般的函数只能通过return返回一个值。
这时可以巧用引用形参了:在函数形参中定义一个计数的引用形参 int &count ,函数搜索过程中计数,并改变count的值,那么函数执行完之后,count的值就代表了出现次数。而return的还是指向第一次出现位置的迭代器。
这样就满足了题目要求。
代码如下:
void swap(int a,int b) { int temp; temp = a; a = b; b = temp; } int main() { int s1 = 10; int s2 = 20; cout << "交换前:s1 = "<<s1<<" , s2 = "<<s2<<endl; swap(s1,s2); cout << "交换后:s1 = "<<s1<<" , s2 = "<<s2<<endl; return 0; }
结果是这样的:
交换前:s1 = 10 , s2 = 20 交换后:s1 = 10 , s2 = 20
并没有改变?!为什么呢?
其实,这里要区分函数的形参和实参。形参是在函数定义过程中定义的,在函数的形参列表中,必须标明参数的类型,是一个变量;实参是在函数调用过程中的,是一个表达式,用来给形参初始化的。
但是,要注意的是,传递的实参并不是对象本身,而是对象的副本,相当于是复制过来的。
所以问题的关键就在这里,上面传递s1, s2实参只是个副本,所以函数改变的只是副本,并没有改变s1,s2本身。
那么,怎么解决这个问题呢?
引用形参!!
把形参改成这样就可以了:
void swap(int &a,int &b)
这次的运行结果为:
交换前:s1 = 10 , s2 = 20 交换后:s1 = 20 , s2 = 10
原因是:引用实际是对象的别名,就像我们的小名儿,代表的是我们本身,而不是我们的克隆(副本)。所以,用引用作为形参,就直接代表对象本身,不是复制来的。函数改变的就是对象本身了。
总结一下:什么情况下使用引用形参呢?
牢记以下四种情况:
需要通过函数调用改变参数对象的时候,如上面的例子;
需要通过一次函数调用获得多个结果值;
在想函数传递大型对象时,复制实参会降低效率,这时可以用引用形参;
如果实参是类类型,且其构造函数为private类型,无法复制,这时只能使用引用形参了。
关于第二点有点难以理解,举例说明一下:
例如,定义一个fing_val函数,在一个整型vector对象的元素中搜索某个特定值,该值可能出现多次。请返回一个迭代器指向该值第一次出现的位置(1),以及出现的次数(2)。
所以需要返回两个值。而一般的函数只能通过return返回一个值。
这时可以巧用引用形参了:在函数形参中定义一个计数的引用形参 int &count ,函数搜索过程中计数,并改变count的值,那么函数执行完之后,count的值就代表了出现次数。而return的还是指向第一次出现位置的迭代器。
这样就满足了题目要求。
代码如下:
vector<int>::iterator find_val(vector<int>::iterator begin, vector<int>::iterator end, int value, vector<int>::size_type &count) { vector<int>::iterator first = end; count = 0; for( ; begin != end ; ++begin) { if(*begin == value) // 以下:如果first还是指向end说明是第一次value出现了,赶紧将first指向该位置。此后,first就不指向end了 if(first == end) first = begin; ++count; } return first; //返回迭代器first,指向value第一次出现的位置 }
相关文章推荐
- C语言学习_查找三分之二
- 要求输出10个学生3门课总平均成绩,以及最高分的学生的数据
- C & C++ 宏与const
- C语言 常用函数
- C++指针与引用
- C++标准库和标准模板库
- 大话设计模式C++版——装饰模式
- 大话设计模式C++版——装饰模式
- C++ sizeof
- 统计选票
- C++继承
- 【c语言】判断一个字符串是否为另外一个字符串旋转之后的字符串
- 【c语言】字符串替换空格:请实现一个函数,把字符串中的每个空格替换成“%20”
- 【C语言】编写函数实现库函数atoi,把字符串转换成整形
- C++ Builder XE7 调用JAVA的JAR文件
- 【C语言】编写函数实现字符串旋转
- [C语言】模拟实现库函数strstr,查找子字符串
- 【C语言】判断一个字符串是否是一个字符串的旋转字符串
- 【C语言】字符串替换空格:实现一个函数,把字符串里的空格替换成“%20”
- 单循环链表的约瑟夫问题(C++)