天天看點

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類型.

繼續閱讀