C++ Primer Plus书之--C++引用与结构体

引用与结构

引用非常适合用于结构和类, 使用结构引用参数的方式与使用基本变量相同, 只需要声明结构参数时使用引用运算符&即可, 如果不希望函数修改传入的结构, 可以使用const

来看一个简单的demo

#include <iostream>
#include <string>
using namespace std;

// 声明一个结构体
struct st1
{
	string  name;
	int made;
	int attempts;
	float percent;
};

// 只是用来显示, 所以使用const引用
// 使用引用的原因是为了节省内存
void display(const st1 & ft);
// 没有使用const是为了在函数内部修改结构体的内容
void set_pc(st1 & ft);
// 返回一个结构体的引用
// 由于只需要修改第一个结构体的内容, 所以第二个结构体引用为const
st1 & accumulate(st1 & target, const st1 & source);

int main()
{
	// 创建几个结构体变量, 并初始化
	// 如果初始值比成员值少, 剩余的成员将被设置成0
	st1 one = {"one", 1, 11};
	st1 two = {"two", 2, 22};
	st1 three = {"three", 3, 33};
	st1 four = {"four", 4, 44};
	st1 five = {"five", 5, 55};
	st1 team = {"team", 0, 0};
	// 不进行初始化
	st1 dup;

	// 默认由于没有对percent进行初始化, 所以percent是0
	display(one);
	// 设置percent
	set_pc(one);
	display(one);
	
	// 将one里的made和attempts加到team中
	accumulate(team, one);
	display(team);
	
	display(accumulate(team, two));
	accumulate(accumulate(team, three), four);
	display(team);
	
	dup = accumulate(team, five);
	cout << "Displaying team : " << endl;
	display(team);
	cout << "Displaying dup after assignment : " << endl;
	display(dup);
	
	set_pc(four);
	// 注意这个写法, 相当于:
	// accumulate(dup, five); dup = four; 这两句的合并
	accumulate(dup, five) = four;
	cout << "Displaying dup after ill-advised assigment :" << endl;
	display(dup);
	return 0;
}

void display(const st1 & ft)
{
	cout << "Name = " << ft.name;
	cout << ", made = " << ft.made;
	cout << ", attempts = " << ft.attempts;
	cout << ", percent = " << ft.percent << endl;
}

void set_pc(st1 & ft)
{
	if (ft.attempts != 0)
		ft.percent = 100.0f * float(ft.made) / float(ft.attempts);
	else
		ft.percent = 0;
}

st1 & accumulate(st1 & target, const st1 & source)
{
	target.attempts += source.attempts;
	target.made += source.made;
	set_pc(target);
	return target;
}

程序运行结果为:

需要注意的地方都用注释写明了, 着重注意一点:

  accumulate(dup, five) = four; 

相当于这两句的合并:

accumulate(dup, five); 
dup = four; 

返回引用与返回值的区别

st1 & accumulate(st1 & target, const st1 & source);

dup = accumulate(team, five);
返回值的话, 相当于将返回结果复制到一个临时变量中, 然后将临时变量copy复制给接收处, 而引用实际是直接把team复制到dup, 其效率更高.
注意: 返回引用的函数实际是被引用的变量的别名. 

 

返回引用时应注意的问题
应避免返回 返回函数执行完毕时不存在的内存单元
, 例如:

const st1 & clone(st1 & ft)
{
    st1 newguy;
    // 复制
    newguy = ft;
    // 返回引用
    return newguy;
}

该函数返回的是一个临时变量(newguy)的引用, 当函数执行完毕的时候newguy将不在存在, 所以返回这种引用是不行的. 
为避免这种问题, 最简单的方法是返回一个作为参数传递给函数的引用.
另一种方法是用new来分配新的存储控件. 

const st1 & clone2(st1 & ft)
{
    st1 * pt;
    // 复制
    *pt = ft;
    // 返回引用
    return *pt;
}

st1 * pt; 创建了一个无名的st1结构, 并让指针pt指向该结构体, 因此*pt就是该结构体. 可以这么使用该函数:
st1 & jolly = clone2(three);
这使得jolly成为新的结构体的引用, 但是有个问题, 就是在不再需要new分配的内存时, 我们应该使用delete来释放他们, 调用clone隐藏了对new的调用, 因此不要忘记使用完毕后dellete

常规返回类型是右值--不能通过地址访问的值, 这种表达式可出现在赋值语句的右边, 但是不能出现在左边, 其他的右值包括字面值(如10.0, 和表达式x + y), 显然, 获取字面值的地址没有意义. 但为何常规和桉树返回值是右值呢? 是因为这种返回值位于临时内存单元中, 运行到下一条语句时, 他们可能不再存在.
 

猜你喜欢

转载自blog.csdn.net/c1392851600/article/details/84700717
今日推荐