作为局部变量的std::string和标准库容器一种内存优化方法

本文探讨了在C++开发中如何优化std::string和std::vector等容器的使用,通过减少堆内存分配来提高效率,并介绍了使用成员变量及自定义分配器的方法。

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

Program received signal SIGBUS, Bus error. 0x0000fffff7f3a1c0 in ?? () from /usr/lib64/libstdc++.so.6 xgdb> bt [ 34000070] #0 0x0000fffff7f3a1c0 in ?? () from /usr/lib64/libstdc++.so.6 [ bl 9402c8da] #1 0x0000fffff7e87e4c in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib64/libstdc++.so.6 Reading in symbols for /usr1/zWX279063/1.10.0/libdtcenter/gtest_1.10.0_dtcenter/src/gtest.cc...done. [ bl 97ee8576] #2 0x000000000265f97c in std::pair<std::string const, testing::styleCheckItem>::~pair (this=0x44e432d0, __in_chrg=<optimized out>) at /usr/include/c++/7.3.0/bits/stl_pair.h:198 [ bl 97fffff0] #3 0x000000000265f9a0 in __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, testing::styleCheckItem> > >::destroy<std::pair<std::string const, testing::styleCheckItem> > (this=0x4758610 <testing::styleCheck::styleCheckData>, __p=0x44e432d0) at /usr/include/c++/7.3.0/ext/new_allocator.h:140 [ bl 940006b6] #4 0x000000000265deb4 in std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<std::string const, testing::styleCheckItem> > > >::destroy<std::pair<std::string const, testing::styleCheckItem> > (__a=..., __p=0x44e432d0) at /usr/include/c++/7.3.0/bits/alloc_traits.h:487 [ bl 94000b33] #5 0x000000000265b1d0 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::_M_destroy_node (this=0x4758610 <testing::styleCheck::styleCheckData>, __p=0x44e432b0) at /usr/include/c++/7.3.0/bits/stl_tree.h:650 [ bl 940014b8] #6 0x0000000002655ec0 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::_M_drop_node (this=0x4758610 <testing::styleCheck::styleCheckData>, __p=0x44e432b0) at /usr/include/c++/7.3.0/bits/stl_tree.h:658 [ bl 940015fc] #7 0x00000000026506b8 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::_M_erase (this=0x4758610 <testing::styleCheck::styleCheckData>, __x=0x44e432b0) at /usr/include/c++/7.3.0/bits/stl_tree.h:1858 [ bl 97fffff5] #8 0x00000000026506a0 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::_M_erase (this=0x4758610 <testing::styleCheck::styleCheckData>, __x=0x44e42940) at /usr/include/c++/7.3.0/bits/stl_tree.h:1856 [ bl 97fffff5] #9 0x00000000026506a0 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::_M_erase (this=0x4758610 <testing::styleCheck::styleCheckData>, __x=0x44e463b0) at /usr/include/c++/7.3.0/bits/stl_tree.h:1856 [ bl 940018b0] #10 0x000000000264a3b4 in std::_Rb_tree<std::string, std::pair<std::string const, testing::styleCheckItem>, std::_Select1st<std::pair<std::string const, testing::styleCheckItem> >, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::~_Rb_tree (this=0x4758610 <testing::styleCheck::styleCheckData>, __in_chrg=<optimized out>) at /usr/include/c++/7.3.0/bits/stl_tree.h:949 [ bl 97ff9d4a] #11 0x0000000002662e70 in std::map<std::string, testing::styleCheckItem, std::less<std::string>, std::allocator<std::pair<std::string const, testing::styleCheckItem> > >::~map (this=0x4758610 <testing::styleCheck::styleCheckData>, __in_chrg=<optimized out>) at /usr/include/c++/7.3.0/bits/stl_map.h:294 [ blr d63f0380] #12 0x0000fffff7b724d0 in ?? () from /usr/lib64/libc.so.6 [ bl 97ffff5a] #13 0x0000fffff7b7262c in exit () from /usr/lib64/libc.so.6 [ bl 94005175] #14 0x0000fffff7b5e040 in ?? () from /usr/lib64/libc.so.6 [ bl 97ffffb0] #15 0x0000fffff7b5e114 in __libc_start_main () from /usr/lib64/libc.so.6 [ bl 97fffd89] #16 0x0000000002201970 in _start () 解释以上gdb错误
最新发布
09-20
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值