進階篇_STL中的容器

Pop_Rain發表於2017-04-28

容器就是STL中的瓶瓶罐罐,就是能夠儲存其他型別的物件的類,是STL的關鍵部件之一。STL的容器分為:順序容器關聯容器

1.順序容器

STL中包括三種基本的順序容器:向量(vector)、線性表(list)、雙向佇列(deque),基於這三種基本順序容器,又可以構造出一些專門的容器,用於比較特殊的資料結構,包括堆(heap)、棧(stack)、佇列(queue)及優先佇列

2.關聯容器

vector<int> vecSalary;
list<string> listname;
map<int, Employee*> mapEmployee;//用於存放Employee*指標的map容器 

3.操作容器中的資料元素、使用迭代器訪問容器中的資料元素


4. 容器中存放物件還是物件指標的選擇

當使用基於連續記憶體的容器時(eg vector容器),在這些容器中插入或刪除元素時,往往會引起記憶體的重新分配或者記憶體的複製移動,在這種情況下,優先選擇存物件的指標;當使用基於節點記憶體的容器時,當進行資料元素的操作時則很少有記憶體的複製移動,為了方便這時可以優先包存物件;如果需要儲存一些機器資源(eg。檔案控制程式碼,命名管道,套接字或者其他類似的資源),通常選擇儲存指向這些物件的指標。要注意的幾點:

1. 小心清理容器中儲存的物件指標,如果容器中儲存的是物件,那麼在容器析構的時候容器會自動清理這些物件。但是,如果容器中儲存的是物件的指標,那麼這些指標的清理工作就是程式設計師的責任了。我們應該咋容器使用完畢後沒注意清理其中儲存的指標,釋放這些指標所指向的物件。

vector<Employee*> vecEmployee;
//對容器進行操作
//在容器使用完畢後,清空容器中儲存的指標,釋放這些指標所指向的物件
for(auto it=vecEmployee.begin(); it!=vecEmployee.end(); ++it)
{
	if(NULL != *(it))
		delete (*it);	//釋放指標所指向的物件 
	(*it) = NULL;	//將指標設定為NULL,防止誤用 
} 
vecEmployee.empty();	//清空整個容器 

2. 為容器中的物件實現拷貝建構函式和賦值操作符。

如果需要將某個物件儲存到容器中,實際上STL會重新生成一個此物件的拷貝,然後將這個拷貝儲存在容器中,源物件將不再使用。所以,為了保證將物件裝入容器時物件能夠被正確地拷貝,需要實現這個物件的類的拷貝建構函式和賦值操作符。

class Employee
{
public:
	Employee(const Employee& rsource)	//拷貝建構函式 
	{
		*this = rsource;	//利用賦值操作符實現物件的拷貝 
	}
	Employee& operator = (const Employee& rsource)	//實現賦值操作符,這裡對類的每個屬性都進行了合理的初始化 
	{
		m_nSalary = rsource.m_nSalary;
		m_strName = rsource.m_strName;
		return *this; 
	}
private:	
	int m_nSalary;
	string m_strName;
}

當然,很多時候無須自己實現類的拷貝建構函式,編譯器會自動建立一個拷貝建構函式,以拷貝記憶體的方式完成類物件的拷貝。但是,這裡要特別注意的是,記憶體拷貝並不能保證類物件被正確地拷貝,特別是當類中有指標作為成員屬性的時候,需要謹慎地實現自己的拷貝建構函式,以保證類物件在裝入容器時能夠正確地拷貝。

3. 使用迭代器刪除容器中的資料元素需謹慎。當使用迭代器刪除容器中的資料元素時,容器中的元素位置將發生變化,所以迭代器所代表的的當前位置也會發生變化,要注意


	for(auto it=vecint.begin(); it!=vecint.end(); ++it)
	{
		if(*it >1000)
			it = vecint.erase(it);	//刪除完成後,將迭代器重新指向正確的位置 
	} 

5. 如何選擇合適的容器