6.2 参数传递
引用传递:引用形参是他绑定的对象的别名;也就是说,引用形参是他实参的别名。
值传递:当实参的值被拷贝给形参时,形参和实参是两个相互独立的对象。
指针传递:与值传递类似,实参的地址值被拷贝给形参。不影响实参本身。
引用形参优势
1.使用形参避免拷贝
拷贝大的类类型对象或容器对象比较低效,甚至有的类根本不支持拷贝操作,这时使用引用形参是比较明智的选择。
例如:
比较两个string对象的长度,因为string对象可能会非常长,所以应该尽量避免直接拷贝他们,这时使用引用形参是最明智的选择。又因为是比较长度无需改变string对象的内容,所以把形参定义成常量的引用。
bool isShorter(const string &s1, const string &s2){
return s1.size()<s2.size();
}
注:如果函数无需改变形参的值,最好将其声明为常量引用。
2.使用引用形参返回额外信息
一个函数只能返回一个值,但有时候函数需要返回多个值,引用形参为我们一次返回多个结果提供了有效途径。
例如:
定义一个find_char函数,返回在string对象中某个特定字符的位置。同时又想返回该字符出现的次数。
int find_char(const string &s, char c, int &occurs){
int ret = s.size();
occurs = 0;
for(int i=0;i<ret;i++){
if(s[i]==c){
if(ret==s.size()){
ret = i;
}
occurs++;
}
}
return ret;
}
void main(){
int ctr;
auto index = find_char(s, 'o', ctr);
}
6.2.3 const形参和实参
指针或引用形参与const
int i = 0;
const int ci = i;
reset(&i);//正确,调用形参是int *的reset函数
reset(&ci);//错误,不能用指向const int对象的指针初始化int *
reset(i);//正确,调用形参是int&的reset函数
reset(ci);//错误,不能把普通引用绑定到const对象ci上
reset(42);//错误,不能把普通引用绑定到字面值上
注:
引用版本的reset
只能使用:int类型对象。
不能使用:字面值、求值结果为int的表达式、需要转换的对象、const int 类型对象。
指针版本的reset
只能使用:int *
注:
C++允许使用字面量来初始化常量引用。
尽量使用常量引用
注:
1、把函数不会改变的形参定义成普通引用是一种常见的错
例如:find_char(string &s1,string &s2)
2、我们不能把const对象、字面量、需要类型转换的对象传递给普通的引用形参。
6.2.4 数组形参
定义和使用作用在数组上的函数有两大性质:
性质1:不允许拷贝数组
性质2:使用数组是(通常)会将其转换成指针
影响1:因为不能拷贝数组,所以我们不能以值传递的方式使用数组形参。
影响2:因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。
管理数组指针形参的三种常用技术
使用标记指定数组长度
此方法一般适用于有明显结束标记且该标记不会与普通数据混淆的情况,例如string类型的数据以空字符作为结束符。
void print(const char *cp){
if(cp){
while(*cp){
cout<<*cp++;
}
}
}
使用标准库规范
这种技术是传递指向指向数组首元素和尾后元素的指针。
void print(const int *beg, const int *end){
while(beg!=end){
cout<<*beg++<<endl;
}
}
显示传递一个表示数组大小的形参