习题答案请参考:C++ Primer 第五版 第6章 6.2——函数参数传递习题答案
目录
6.2 函数参数传递
参数传递有两种:
(1)引用传递: 形参将绑定到对应的实参上,实参值会改变
(2)值传递:将实参的值拷贝后赋给形参,形参和实参是相互独立,不会影响实参的值
6.2.1 传值参数(值传递)
指针形参
通过指针形参,可以改变指针所指的对象的值,但并不会改变指针的地址
如:
void reset(int *ip)
{
*ip = 0; //ip所指的对象值改变
ip = 0; //只改变了ip的局部拷贝,实参为被改变
}
调用reset函数之后,实参所指的对象值被置为0,但实参本身并没有改变(这里的实参是一个指针,相当于是一个地址):
int i=42;
reset(&i);
cout << "i= " << i << endl;
6.2.2 传引用参数(引用传递)
引用形参相当于是实参的另一个名字,所以会改变实参的值
如:
void reset(int &i) //引用形参
{
i = 0;
}
调用reset函数时,我们直接传入对象而非对象地址(这里是细节,一定要注意和指针区别,指针需要传入地址!!):
int j = 42;
reset (j); //引用传递,值会被改变
cout << "j= " << j << endl; // 输出j=0;
小贴士!!!
在实际中,尽量避免拷贝而使用引用形参,当遇到不会改变对象的内容时,将形参定义成常量引用,即:const string &s1。(细节,面试时候可能就会有此考点!!)
使用引用形参返回多个结果
函数返回多个值时,引用形参就提供了有效途径
如:定义名find_char的函数,返回string对象中某个指定字符出现的位置和出现的总次数
思路:给函数传入一个额外的引用实参,令其保存字符出现的次数
//返回s中c出现的位置索引
//引用形参occurs负责统计c出现的总次数
//const string &s则为常量引用
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; //记录c第一次出现的位置
++occurs; // 将位置加1
}
}
return ret; //出现次数通过occurs隐式地返回
}
调用上述函数如下:
auto index = find_char(s,'o',ctr);
//返回s中c出现的位置索引
//引用形参occurs负责统计c出现的总次数,额为的引用形参
//const string &s则为常量引用
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; //记录c第一次出现的位置
++occurs; // 将位置加1
}
}
return ret; //出现次数通过occurs隐式地返回
}
int main()
{
size_t cnt = 0;
string str("my name is lianglinlin");
auto index = find_char(str, 'l', cnt);
cout << index << ' ' << cnt << endl;
return 0;
}
6.2.3 const形参和实参
小贴士!!!
当形参为const时,其实是被忽略掉cosnt的,即在传递常量对象或者非常量对象都是可以的(细节,注意!!)
这样就要注意如下错误的定义:
void fcn(const int i){ 能够读取i,但是不能向i写值 }
void fcn(int i) { } 这种定义就错误了,因为上边const被忽略了,所以这里就重复定定义了
小贴士!!!
尽量使用常量引用:把函数不会改变的形参定义成乘凉引用(细节,注意!!)
6.2.4 数组形参
数组要记住两点:
(1)不允许拷贝数组
(2)数组在使用时会被转换为指针
故数组作为形参时,要注意:
(1)不能值传递
(2)传递数组,实际传递的是数组的首元素的指针
管理指针形参的三种技术:
(1) 数组本身包含一个结束标记,如跟着一个空字符串
void print(const char *cp)
{
if (cp) // 若cp不是一个空指针
while (*cp) // 指针指的不是空字符
cout << *cp++; //输出当前字符并将指针向前移动一个位置
}
(2) 使用标准库规范,传递指向数组首元素和尾元素的指针
void print(const int *beg, const int *end)
{
//输出beg和end之间(不含end)的所有元素
while (beg!=end)
cout << *beg++<<endl; //输出当前字符并将指针向前移动一个位置
}
(3)显示传递一个表示数组大小的形参,大小可以用end-begin求得
void print(const int ia[], size_t size)
{
for (size_t i = 0; i != size;++i)
cout << ia[i]<<endl;
}
6.2.5 main:处理命令行选项
argc:表示数组中字符串的数量
argv:是一个数组