2012-01-31 65 views
1

我正在研究如何創建自定義容器,例如eastl的容器和其他幾個模型,我發現它們都使用「分配器」,很像std::vectorstd::allocator一樣。這讓我想,爲什麼一個矢量容器的新實現使用分配器時,他們通常有基本的內存管理覆蓋newdelete矢量(容器)是否需要使用「分配器」?

+0

我認爲你的假設是錯誤的。我無法理解以「爲什麼」開頭的最後一點,我認爲這是虛構的。 – 2012-01-31 06:46:10

+0

如果你在看什麼分配器和他們扮演什麼角色,請閱讀下面的Als的答案。 如果您正在查看代碼並查看分配器對象,儘管默認分配器被重用,這是因爲STL(作爲_template_庫)具有假設(例如,每個容器定義稱爲迭代器和const_iterator和分配器的類,並且每個子類有一定的屬性)。關聯它們(通常通過typedef和override函數)是爲了完整性而完成的 – Fox 2012-01-31 06:59:08

+0

(在上面的評論中)我找不到在評論中輸入行分隔符的方法。如果是這樣的話,請刪除這條評論,如果我錯過了方法,請幫助我 – Fox 2012-01-31 07:02:58

回答

4

能夠在程序級別替換operator new()operator delete()(及其陣列版本)可能足以滿足小程序的需求。如果你的程序由數百萬行代碼組成,運行許多不同的線程是不合適的。你經常想要甚至需要更好的控制。爲了使自定義分配器有效,還需要能夠使用與外部分配器相同的對象分配子對象。

例如,考慮在迴應可能運行多個線程的某種服務器中的請求時使用內存競技場。從operator new()獲取內存可能相當昂貴,因爲它涉及分配一個鎖,並在越來越多的碎片堆中找到合適的內存塊。爲了避免這種情況,您只需要分配幾塊內存(理想情況下只有一塊,但您可能不知道預先需要的大小),並將所有對象放在那裏。分配器可以做到這一點。要做到這一點,你需要通知所有的實體分配這塊內存的內存,即你需要將分配器傳遞給可能分配內存的所有東西。如果您分配了例如std::vector<std::string, A>std::stringstd::string對象應該知道分配器:只告訴std::vector<std::string, A>分配內存的位置和方式不足以避免大部分內存分配:您還需要將它告訴std::string(實際上,對於合適的分配器,實際上是std::basic_string<char, std::char_traits<char>, B>鍵入B這與A有關)。也就是說,如果你真的想要控制你的內存分配,你一定要把分配器傳遞給分配內存的所有東西。使用替換版本的全局內存管理工具可能會對您有所幫助,但它受到相當的限制。如果你只是想寫一個自定義容器,並且內存分配不是你關心的東西,你不一定需要打擾。然而,在長時間運行的大型系統中,內存分配是衆多問題之一。

+0

你的線程示例不會讓IMO更有意義。在那種情況下,我只是使用基於線程本地存儲的全局分配器來實現其數據結構。在我看來,更簡單,更簡單,更安全。 – 6502 2012-01-31 07:21:55

+1

您是否在代碼庫上使用了這種方法,該代碼庫由多個對代碼有貢獻的顯着大小組成?你是如何爲所有項目準確地取代這些運營商的?在我爲之工作的組織中,從來都不是所有程序都使用共同設置的情況。 ...即使代碼不包含幾百萬行代碼。對分配機制進行本地控制對我來說很有用,因爲我無法控制整個程序。 – 2012-01-31 09:01:34

1

分配器是定義標準庫容器使用的內存模型的類。

每個標準庫容器都有自己的默認分配器,但容器的用戶可以在默認情況下提供自己的分配器。
這是爲了增加靈活性。
它確保用戶可以提供自己的分配器,它除了提供常規堆外,還提供內存管理的一種替代形式(例如:內存池)。

0

如果你想生產一個兼容標準的容器,那麼答案當然是肯定的...分配器在標準中描述,所以它們是必需的。

然而,根據我個人的經驗,分配器並沒有那麼有用......因此,如果您正在開發一個容器以供特定用途來克服標準容器的某些結構性限制,那麼我會建議忘記分配器,除非您真的看到使用它們的原因。

如果你正在開發一個容器,只是因爲你認爲你可以比標準向量做得更好,那麼我的猜測是你正在浪費你的時間。我不喜歡分配器的想法設計(放棄應該不存在的東西),但幸運的是,它們可以被忽略。分配器在你不需要它們(即總是)時唯一的煩惱可能是在錯誤消息中有更多的混淆。然而,無論如何,這都是一團糟。

相關問題