实际项目中,往往看到好多项目把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),内存也很紧凑,保证高效。