作為區域性變數的std::string和標準庫容器一種記憶體優化方法
阿新 • • 發佈:2019-02-15
實際專案中,往往看到好多專案把std::string, std::vector作為區域性變數直接使用的情況。 類似下面std::string的用法:
void SomeClass::Fun()
{
std::string str = "abcd";
str += "efgh";
}
下面是std::vector的類似例子:
void SomeClass::Fun2() { std::vector<int> iv; iv.push_back(22); DoFun2(iv); }
在後臺伺服器出現上面類似的程式碼最好還是優化一下。上面程式碼涉及堆記憶體的申請和釋放,執行頻繁的話,會產生碎片。
一種優化方法是,把std::string作為SomeClass的成員變數:
class SomeClass
{
private:
std::string m_str;
};
void SomeClass::Fun()
{
m_str.clear(); // 每次用的時候,清一下
m_str = "abcd";
m_str += "efgh";
}
std::string的特點是clear()的時候,只清內容,不釋放記憶體。std::vector也有這類特點,也可用類似的方法。
還有一類容器,比如std::list, std::map, xxx::hash_map等, clear()的時候,同時也會釋放記憶體,這個也好辦,傳一個allocator給他。下面用 std::list舉例,std::string麻煩一點, 得用std::basic_string.
class SomeClass
{
private:
std::list<int, __gnu_cxx::pool_alloc<int> > m_list;
};
這樣呼叫m_list.clear()的時候,記憶體的釋放從pool_alloc釋放。避免了從堆中分配和釋放了。
上面一種方法如果SomeClass的物件生命週期結束了,allocator中的記憶體還是會釋放。我們可以考慮第二種方法,引入一個全域性性質的allocator,只要型別一樣的區域性容器都可以用。這樣類物件的生命週期結束了,也不會引起記憶體釋放。
YourAllocator<int> g_intAllocator; void SomeClass::Fun() { std::vector<int, YourAllocator<int> > v(g_intAllocator); UseV(v); }
YourAllocator,Linux上可以用__gnu_cxx::pool_alloc. 其他需要int的區域性容器變數,可以共用這個g_intAllocator。這樣記憶體的申請和分配都在g_intAllocator內部進行,都是O(1),記憶體也很緊湊,保證高效。