引用非常适合用于结构和类,确实引入引用的主要使为了用于这些数据类型的,而不是基本的内置类型。使用结构引用参数的方式与使用基本变量引用相同,只需要在声明结构参数时使用引用运算符即可。
#include <iostream>
#include <string>
using namespace std;
struct free_throws
{
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);
const free_throws& clone( 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 = { "Throwgoods",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);
cout << "display team:\n";
display(team);
cout << "display dup after assignment:\n";
display(dup);
set_pc(four);
accumulate(dup, five) = four;
cout << "displaying dup after ill-advised assignment:\n";
display(dup);
const free_throws& jolly = clone(dup);
display(dup);
return 0;
}
void display(const free_throws& ft)
{
cout << "name: " << ft.name << '\n';
cout << " made: " << ft.made << '\t';
cout << "attempts: " << ft.attempts << '\t';
cout << "percent: " << ft.percent << '\n';
}
void set_pc(free_throws& ft)
{
if (ft.attempts != 0)
{
ft.percent = 100.0f * float(ft.made) / float(ft.attempts);
}
else
{
ft.percent = 0;
}
}
free_throws& accumulate(free_throws& target, const free_throws& source)
{
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}
const free_throws& clone( free_throws& source)
{
free_throws* pt = new free_throws;
*pt = source;
delete pt;
return *pt;
}
这里需要注意以下问题:
1.函数的返回值为什么要返回引用?
如果accumulate函数返回一个结构,而不是指向结构的引用,将把整个结构赋值到一个临时的位置,再将这个拷贝赋值给一个dup,但是返回引用时,直接把team赋值到dup,效率更高。
2.返回引用时需要注意的问题?
返回引用时最重要的一点时,应避免返回函数终止时不存在的内存单元引用。为避免这个问题,最好的方法就是返回一个作为参数传递给函数的引用。这个引用将指向函数使用中的数据,因此返回的数据也将指向这些数据。另一种方法时使用new来分配新的存储空间。
3.为何将const用于引用返回类型。
accumulate(dup, five) = four;这条语句可以编译通过,主要是因为左边的表达式是一个可以修改的左值,这和赋值表达式的概念是相符的,因为在赋值语句中,左边必须是可修改的左值,也就是说在赋值表达式中,左边的子表达式必须表示一个可修改的内存块。他确实表示了这么一块内存块所以可以编译通过。
如果在代码中不允许由这种类型的赋值操作,只需要将该函数的返回值声明为const引用。
const free_throws& accumulate(free_throws& target, const free_throws& source);
这样有一定的好处,就是减少了犯错的可能性,然而省略const可以让代码编写更简短,但是含义相对模糊。但是在有些情况下省略const也是有一定的道理,比如在重载运算符<<的时候.