Effective STL: 43 - 50 在程序中使用STL

43.算法調用優先於手寫的循環。

算法的內部是循環,更進一步,由於STL算法涉及面很廣,所以本該編寫循環來完成的任務也可以用STL算法完成。

一個非常典型的例子:

如果有一個Widget類:

class Widget
{
public:
	void redraw() const;
};
當需要調用每個Widget的redraw函數時,可以這樣:

vector<Widget> v;
for(vector<Widget>::iterator it = v.begin(); it != v.end();++it)
	it->redraw();
也可以選擇用for_each算法:

vector<Widget> v;
for_each(v.begin(),v.end(),mem_fun_ref(&Widget::redraw));
推薦採用算法的方式。


有三個原因:

1.效率:算法通常比程序員自己寫的循環效率更高。

2.正確性:自己寫循環比使用算法更容易出錯。

3.可維護性:使用算法的代碼通常比手寫循環的代碼更加簡潔明瞭。


但是如果想表明在一次迭代中該完成什麼工作,使用循環比使用算法更爲清晰。比如說要確定一個容器中第一個大於x,小於y的元素,使用循環可以這樣實現:

vector<int> v;
int x,y;
……
vector<int>::iterator it = v.begin();
for(; it != v.end(); ++it)
{
	if(*it > x && *it < y)
		break;
}
當然也可以定義一個仿函數:

class BetweenValue
{
private:
	int lowVal;
	int hignVal;
public:
	BetweenValue(int low = int(),int high = int()):lowVal(low),hignVal(high){}
	bool operator()(int val) const
	{
		return val > lowVal && val < hignVal;
	}
};

這裏書上說的貌似有點問題,書上說,如果在函數裏調用創建的仿函數會出現問題。如果仿函數定義成模板,則根本不能通過編譯,如果設計成類而不是模板的話,也是有問題。因爲在函數內部聲明的類是局部類,而局部類不能作爲模板的類型實參(如find_if所需要的仿函數類型)。

而事實上是可以的,如下面的代碼:

#include <iostream>  
#include <vector>  
#include <string>  
#include <algorithm>  
#include <iterator>

using namespace std;  

class BetweenValue
{
private:
	int lowVal;
	int hignVal;
public:
	BetweenValue(int low = int(),int high = int()):lowVal(low),hignVal(high){}
	bool operator()(int val) const
	{
		return val > lowVal && val < hignVal;
	}
};

void FindFirst(const vector<int> &ivec,int x,int y)
{
	vector<int>::const_iterator it = find_if(ivec.begin(),ivec.end(),BetweenValue(x,y));

	cout << *it << endl;
}

int main()
{
	vector<int> ivec;
	for(int i = 9; i <= 14; ++i)
		ivec.push_back(i);

	FindFirst(ivec,10,20);

	return 0;

}

唯一要注意的是:當函數的形參是const類型的容器時,使用容器的迭代器務必要使用const_iterator類型。


44.容器的成員函數優先於同名的算法。

1.成員函數往往速度快。

2.c成員函數通常與容器(特別是關聯容器)結合得更加緊密,這是算法所不能比的。


45.正確區分count,find,binary_search,lower_bound,upper_bound和equal_range。

對於未排序的區間,判斷是否存在給定值,用find。對於已經排序的區間,用binary_search。

對於排序區間,如果要找給定值在哪裏,equal_range不僅完成了find的工作,同時也代替了count。

結論如下表所示:



46.考慮使用函數對象而不是函數作爲STL算法的參數。

原因很簡單,使用仿函數效率更高。


47.避免產生“直寫型”(write-only)的代碼。

將複雜語句分解成易於理解的簡單語句,並且加上一些註釋。


48.總是包含正確的頭文件。

1.幾乎所有的標準STL容器都被聲明在與之同名的頭文件中。

2.除了4個STL算法以外,其他所有的算法都被聲明在<algorithm>中,這4個算法是accumulate,inner_product,adjacent_difference和partial_sum。這4個被聲明在<numeric>中。

3.特殊類型的迭代器,包括istream_iterator等,被聲明在<iterator>中。

4.預定義的仿函數以及配接器,被聲明在<functional>中。


49.學會分析與STL相關的編譯器診斷信息。


50.熟悉與STL相關的Web站點。


發佈了63 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章