天天看点

C++学习-引用作为函数参数

在我们的编程过程中,我们经常将引用用作函数参数, 使得函数中的变量名成为调用程序中的变量的别名.这种传递参数的方法成为按引用传递.

但是在函数中使用引用,往往会改变被引用对象的值.所以引入const.将引用参数声明为常量数据的引用的理由有三个:

(1) 使用const可以避免无意中修改数据的编程错误;

(2) 使用const使函数能够处理const和非const实参,否则只能接收非const实参;

(3) 使用const引用使函数能够正确生成并使用临时变量.

下面是将引用用于结构的例子:

// strc_ref.cpp -- using structure references

#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()
{
	// partial initialization - remaining members set to 0
	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 };

	// no initialization
	free_throws dup;
	
	set_pc(one);
	display(one);
	accumulate(team,one);
	display(team);

	// use return value as argument
	display(accumulate(team,two));
	accumulate(accumulate(team,three),four);
	display(team);
	
	// use return value in argument
	dup = accumulate(team,five);
	std::cout << "Displaying team:\n";
	display(team);
	std::cout << "Displaying dup after assignment:\n";
	display(dup);
	set_pc(four);
	
	// ill-advised assignment
	// 这条语句在这里是可行的,因为函数的返回值是一个引用;如果
	// 函数按值返回,这里将不能通过编译
	accumulate(dup,five) = four;
	std::cout << "Displaying dup after ill-advised assignment:\n";
	display(dup);
	
	return 0;
}
/*
 * 函数名称: display()
 * 功能描述: 使用const 引用参数,显示结构的内容,而不修改它;
 * 			 也可使用按值传递,但与复制原始数据的拷贝相比,
 *			 使用引用可以节省时间和内存;
 */
void display(const free_throws &ft)
{
	using std::cout;
	cout << "Name: " << ft.name << '\n';
	cout << " Made: " << ft.made << '\t';
	cout << "Attempts: " << ft.attempts << '\t';
	cout << "Percent: " << ft.percent << '\n';
}

/*
 * 函数名称: set_pc()
 * 功能描述: 形参ft为引用,ft指向实际引用的变量,在这里按值传递不可用;
 * 			 可以使用指针传递
 */
void set_pc(free_throws &ft)
{
	if (ft.attempts != 0)
		ft.percent = 100.0f * float(ft.made)/float(ft.attempts);
	else
		ft.percent = 0;
}

#if 0
// 如果使用指针进行参数传递,调用时,set_pc(&one)
void set_pc(free_throws *pt)
{
	if (ft->attempts != 0)
		ft->percent = 100.0f * float(ft->made)/float(ft->attempts);
	else
		ft.percent = 0;

}
#endif

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

引申问题:

(1)为何要返回引用?

 如果正常按值返回,先是return后面的表达式计算,然后把计算结果复制到一个临时位置,然后再将这个临时拷贝值赋给保存变量;

而引用是直接将被引用对象复制给保存变量.

(2)返回引用时需要注意的问题?

最重要的一点是,避免返回函数终止时不再存在的内存单元引用.(避免这种问题的最简单方法就是返回一个作为参数传递给函数的引用.另一种方法就是用new来分配新的内存空间,并返回指向该内存空间的指针)

(3)为何将const用于引用返回类型?

避免accumulate(dup,five) = four;这种用法的出现,将返回值类型声明为const类型.

继续阅读