[英]Moving C++ objects, especially stl containers, to a specific memory location
我正在與一個內存管理器合作,有時候想要對內存進行碎片整理。 基本上,我將查看內存管理器分配的對象列表並重新定位它們:
class A {
SomeClass* data; // This member is allocated by the special manager
};
for(... each instance of A ...)
a.data = memory_manager.relocate(a.data);
memory_manager.relocate()
將memcpy()
將數據的內容轉移到新位置,並返回指針。
盡管對於memcpy()
C ++類來說它通常不是慣用的,但考慮到我控制將與內存管理器一起使用的(少數)類的實現,它在這種情況下似乎是一個有用的解決方案。
問題是其中一個類使用std::map
,就我而言,這是一個不透明的類。 我當然不認為我可以memcpy()
它。 在任何情況下我都可能無法使用std :: map。 據我所知,它可以分配幾塊內存。
我能想到的最好的解決方法很簡單。 由於碎片化的內存管理器將新的分配放在更有利的位置,我需要做的就是重新分配它然后刪除舊的:
for(... each instance of A ...) {
stl::map<something>* tmp = a.the_map;
a.the_map = new stl::map<something>(tmp);
delete tmp;
}
無論如何,這讓我想知道:
C ++是否具有將對象移動/復制到特定內存位置的語義或習語?
是否可以將stl容器的內容移動到特定的內存位置?
編輯:雖然我沒有指出,我顯然會將一個allocator參數傳遞給std :: map。 基於我得到的信息性答案,我意識到我在初始問題中發布的解決方法可能是減少碎片的唯一方法。 通過使用map的復制構造函數(和allocator模板參數),可以正確地重新分配映射使用的所有內存。
正如評論所指出的,這主要是一個理論問題。 內存碎片很少需要擔心。
每次插入新鍵,值對時,映射都會分配一個節點來存儲它。 這種分配如何發生的細節由地圖使用的分配器決定。
默認情況下,在std::map<K,V>
創建映射時std::map<K,V>
將使用默認分配器,它在堆上創建節點(即使用new
/ delete
)。
您不希望如此,因此您必須創建一個自定義分配器類,該類根據內存管理器的要求創建節點。
創建一個allocator類並不簡單。 此代碼顯示了如何完成,您必須根據自己的需要進行調整。
一旦你有了你的分配器類(假設你稱之為MemManagerAllocator
),你必須將你的地圖定義為std::map<K, V, MemManagerAllocator>
,然后像使用常規地圖一樣使用它。
就個人而言,我需要有一個非常糟糕的內存碎片問題才能解決所有麻煩。
C ++對象的內容將分散在堆中。 STL對象(例如容器或字符串等)可能會將其元數據存儲在堆棧中(如果不將其放在動態內存中)......但是內容會分散在堆中。
跟蹤對象的所有元素以及對這些元素的所有引用將是一項艱巨的任務。 語言必須提供某種形式的“鈎子”或事件,以便跟蹤記憶塊之間的關系。
所以不,你不能只記憶一個任意的STL對象。
Afaik壓倒新的不是靈丹妙葯,它是一個“進程全局”概念,因此嘗試將新聞本地化為線程 - 對象 - 分配對是不可能的。 這種本地化將使您能夠將內存組合在一起。
您可以編寫自己的容器,顯式地使用自定義內存分配器(顯式,因為您提供了必要的對象標識信息),並且有一些自定義分配器。
您可以使用新的展示位置?
void* adress = new void[size_of(*old_map_ptr)]; // or wherever you want it in your memory
map<type> new_map* = new (adress) map<type>(*old_map_ptr);
delete old_map_ptr;
不,C ++本身只管理內存,但你可以通過實現std :: map :: allocator來幫助stl實現它,它會一直這樣做,所以你不需要memcpy它。
您沒有提到您正在編碼的平台,或者是否允許這樣做。 但是在Linux和GCC中,C ++默認分配器是用malloc
實現的。
malloc
可以被覆蓋並替換為您自己的內部分配器。
我會按如下方式實現這個malloc
:
在一般情況下,只需遵循原始的malloc
。 無論何時,您都可以更改malloc
函數的行為,以返回指向您准備的特殊內存區域的指針。
因此,在創建這個特定的std::map
你會給malloc
一個提示。 (通過全局變量或其他一些通信手段。)
更新:alemjerus建議實現std::map::allocator
,這是一個更清晰的方式在同一主題,也是平台無關。
您可以使用placement new來定義base std :: map對象所在的位置。 但是大部分空間將通過std :: map在堆上分配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.