3.1.将引用用于结构
引用非常适合用于结构和类,而引入引用的目的也是为了用于这些类型。
有如下结构定义:
struct free_throws
{
std;;string name;
int made;
int attempts;
float percent;
};
//则可以这样编写函数原型:
void set_pc(free_throws & ft);
//如果不希望函数修改传入的机构,可使用const:
void display(const free_throws & ft);
下面通过一个示例来展示如何将引用用于结构,并展示它一些有趣的特点:
#include<iostream>
#include<string>
struct free_throws
{
std::string name;
int made;
int attempts;
float percent;
};
void display(const free_throws & ft);
void set_pc(free_throws & ft);
free_throws & accumulate(free_throws & target, const free_throws & source);
int main() {
free_throws one = { "Ifelsa Branch", 13, 14 };
free_throws two = { "Andor Knott", 10, 16 };
free_throws three = { "Minnie Max", 7, 9 };
free_throws four = { "Whily Looper", 5, 9 };
free_throws five = { "Long Long", 6, 14 };
free_throws team = { "Thorwgoods", 0, 0 };
free_throws dup;
set_pc(one);
display(one);
accumulate(team, one);
display(team);
//有趣的地方①
display(accumulate(team, two));
accumulate(accumulate(team, three), four);
display(team);
dup = accumulate(team, five);
std::cout << "Displaying team:\n";
display(team);
set_pc(four);
accumulate(dup, five) = four; //②
std::cout << "Displaying dup after ill advised assignment:\n";
display(dup);
system("pause");
return 0;
}
void display(const free_throws & ft) {
using std::cout;
cout << "Name: " << ft.name << '\t';
cout << "Made: " << ft.made << '\t';
cout << "Attempts: " << ft.attempts << '\t';
cout << "Percent: " << ft.percent << '\n';
}
//函数set_pc的代码设置成员percent,按值传递不可行,所以按引用传递
void set_pc(free_throws & ft) {
if (ft.attempts != 0)
{
ft.percent = 100.0f * float(ft.made) / float(ft.attempts);
}
else
{
ft.percent = 0;
}
}
//函数accumulate()接收两个结构参数,并将第二个结构的成员attempts和made的数据添加到第一个结构的相应成员中。
free_throws & accumulate(free_throws & target, const free_throws & source) {
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}
输出为:
- ①:函数accumulate()修改了team,再返回指向它的引用,接下来,accumulate()的返回值作为参数传递给了display(),这意味着team传递给了display(),与下面代码等效:
accumulate(team, two); display(team);
-
- ②:这以独特的方式使用了accumulate();
这条语句将值赋给函数调用,这是可行的相当于:
accumulate(dup, five); duo = four;
这样的操作并不好。
-
- 返回引用时需要注意的问题
应避免返回函数终止时不再存在的内存单元引用,您应避免:
const free_throws & clone2 (free_throws & ft) { free_throws newguy; newguy = ft; return newguy; }
newguy为临时变量的引用,函数运行完毕后它将不再存在,为避免这种问题,最好返回一个作为参数传递给函数的引用,作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。
另一种方法是用new来分配新的存储空间:
const free_thorws & clone(free_throws & ft) { free_throws * pt; *pt= = ft; return *pt;
第一条语句创建一个无名的free_throws结构,并让指针pt指向该结构,因此*pt就是该结构。上述代码似乎会返回该结构,但函数声明表面,该函数实际上将返回这个结构的引用。
调用clone()隐藏了对new的调用,这使得以后很容易忘记使用delete来释放内存。