c 中的STL的vector容器

2021-09-18 07:10:57 字數 2792 閱讀 6601

c++中我相信大家經常要用到stl裡面的各種容器來存放自己的資料,既然我們用的這麼頻繁那麼就相應該有一些疑問?

1.容器裡面什麼時候應該存指標?

2.容器裡面什麼時候應該存物件?

3.容器怎麼在遍歷的時候刪除某元素?

4.容器應該怎麼釋放掉?

一.分析一下stl裡面工作方式

對於內建型別(int float char等),容器的工作方式是純粹的位拷貝,這裡沒有什麼需要多說的。

對於自定義的物件,容器容納了物件(比如通過insert或push_back等),但容器中存放的物件不是你給它們的那個物件,因為兩個物件在記憶體中的位置不一樣。此外,當你從容器中獲取乙個物件時,你所得到的物件不是容器裡的那個物件。取而代之的是,當你向容器中新增乙個物件(比如通過insert或push_back等),進入容器的是你指定的物件的拷貝。拷進去,拷出來。拷貝是stl的方式。可以通過自己寫乙個例子列印出位址來看。

二.存放物件的情況

明白了容器的工作方式,那麼進一步來討論容器存放物件和指標在操作過程中的開銷。內建型別的資料進行拷貝的方式是位拷貝,自定義型別的資料進行拷貝會呼叫類的拷貝建構函式,這個函式是每個類都有的,如果類中沒有顯式的宣告那麼編譯器也會給提供乙個預設的拷貝建構函式。如果乙個類的資料非常多,或者包含其他複雜自定義型別,那麼此時類的拷貝構造的開銷是非常大的。此時容器中要是存放的是物件vector,那麼乙個簡單的插入操作的代價也是驚人的,更別說什麼排序之類的操作,很容易帶來效能上的瓶頸,這個時候就需要在容器中存放物件的指標vector,這樣的話就避免了這些多餘的拷貝消耗,因為指標就是乙個機器字長,拷貝的代價可以忽略不計。

下面的結果是在release版本下,並且編譯器的優化關閉的情況下,這和我們目前的客戶端設定一樣:

max = 4000

max = 40000

max = 400000

上面的資料沒有用統計學的方法去測試,只是取了一次結果,我測試了多次結果在數量級上是一樣的(用上面的資料只是說明拷貝的代價是巨大的,並沒有強調必須用指標)。

分析完了拷貝的效能消耗,再看看另乙個問題,就是宣告了乙個存放基類物件的容器,如果此時向容器中插入子類的物件,那麼子類特有的那些內容就會被無情剝離(slicing)。這是乙個很嚴重的問題。解決的方法還是使用基於指標的容器。

三.存放指標的情況

上面提到的兩個問題用指標確實比用物件好,問題不是這麼絕對。在上面考慮拷貝消耗的時候有個前提:如果乙個類的資料非常多,或者包含其他複雜自定義型別,並且需要大量的使用需要容器內部物件拷貝的操作。如果乙個物件中就是幾個簡單的內建型別,或者乾脆就是乙個簡單的內建型別的資料,那麼再用指標可真是得不償失了,因為使用指標需要程式設計師去管理記憶體。完全沒有必要為了節省幾個int型別的拷貝消耗而去自己去做記憶體的管理,確實完全沒有必要。用指標就需要自己手動的去管理這些指標所指向的記憶體,stl容器確實可以動態申請記憶體使自己變大以容納更多的元素,但這些動態空間存放的是你的指標,而並不是你指標指向的動態記憶體,你的指標記憶體當然需要你去管理,如果實在不想做這些管理工作,可以去使用智慧型指標。

四.總結一下存指標與物件

1.stl容器可以存放內建型別、自定義型別、指標型別的元素。

2.元素如果是內建資料型別,那麼就存放資料本身。

3.元素如果是複雜型別,並且在使用容器的過程中需要容器的元素進行大量的拷貝操作的時候,就要考慮在容器中放入指標;

4.存放指標容易出現記憶體的洩露,所以在使用的時候需要考慮清楚,如能介面設計的合理,能保證容器在使用的過程中不進行大量的拷貝工作,在容器中存放物件是最好的了。

5.使用智慧型指標是一種兩種優點都兼備的,既有指標的操作效率,又避免了自己手動管理記憶體帶來的問題。

6.指標可以解決派生類物件存放在使用基類例項化的容器中的剝離(slicing)問題。

在考慮容器中是存放物件還是指標的時候腦子裡時刻要想到,我的操作需要容器做多少拷貝工作,這些拷貝操作帶來的損耗能否接受,從這個本質問題上把握好了,選擇起來就不是問題了,要根據實際情況靈活運用。

五. stl遍歷過程中刪除元素

如果想在容器遍歷過程中刪除裡面某個值時,用迭代器(這是最簡單的方法),看下面**:

std::list< int> list;

std::list< int>::iterator itlist;

for( itlist = list.begin(); itlist != list.end(); )

else

itlist++;

}

或者:

std::list< int>::iterator itlist;

for( itlist = list.begin(); itlist != list.end(); )

else

itlist++;

}

重點是當刪除後就要往後移一位,不然下次遍歷到那時,已經不存在,就會報錯的。

六. stl中刪除元素釋放問題

stl中不管是erase或remove都不會釋放物件的記憶體空間,他只是釋放了stl裡面用來存放這個物件或指標的空間,所以依然需要自己去手動釋放,並且釋放是有先後順序的,要先delete 在呼叫stl裡容器對應的erase函式。

listm_list;

list::iterator ite;

for( ite = m_list.begin(); ite != m_list.end(); ++ite)

總之一條原則, 你 new 的, 你去 delete 釋放。不是你 new 的, 就不該你去釋放。你往 list 裡面插入元素時所需的記憶體是 list 自己申請的, 那它就會自己釋放。但是你存在裡面的物件不是他的,他不會管!

STL中的 vector 容器詳解

vector作為stl提供的標準容器之一,是經常要使用的,有很重要的地位,並且使用起來也是灰常方便。vector又被稱為向量,vector可以形象的描述為長度可以動態改變的陣列,功能和陣列較為相似。實際上更專業的描述為 vector是乙個多功能的,能夠操作多種資料結構和演算法的模板類和函式庫,vec...

c 中的vector容器

在c 中,vector是乙個十分有用的容器,下面對這個容器做一下總結。1 基本操作 1 標頭檔案 include.2 建立vector物件,vectorvec 3 尾部插入數字 vec.push back a 4 使用下標訪問元素,cout 5 使用迭代器訪問元素.vector iterator i...

STL中的序列式容器 vector(向量)

vector 是向量型別,它可以容納許多態別的資料,如若干個整數,所以稱其為容器。vector 是c stl的乙個重要成員,使用它時需要包含標頭檔案 include vector 容器的長度不固定,能夠在程式執行時動態地改變,故也稱動態陣列。有以下方式,舉例說明如下 vector int a vec...