鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

STL等容器使用时,需做规格预估与预留,避免容器内存自动扩张

【说明】 主要针对std::vector和std::string或者类似的内存连续的顺序型容器。针对这种类型的容器插入大量数据之前,可以对容器的规格进行预留,避免容器因内存不足自动扩张内存带来的性能影响。

【原理】 内存连续的顺序型容器的内存是自动管理的,按需扩张。在数据插入过程中出现内存耗尽的情况,容器会重新申请一块更大的内存空间,然后把当前的每一个元素拷贝到新的地址,再释放原来的内存,最后在插入新的元素。在内存的扩张过程中,会产生大量耗时操作,如内存申请和释放、数据的拷贝等。因此如果能提前知道规格,可以提前设置规格,就能避免频繁的扩张。

【注意事项】 提前预留规格,可能导致内存的利用率降低,需要在空间与时间之间做好权衡。

【案例】

优化前
std::vector<uint32_t> GetKeyOfMap(const std::map<uint32_t,uint32_t> &map)
{
    std::vector<uint32_t> vec;
    for(auto &item : map){
        vec.emplace_back(item.first);
    }
    return vec;
}

说明:当map的数量比较多少时, vec变量会多次扩张,可能出现8->16->32->64.....->1024等多次扩张(内存申请释放)和多次的内存拷贝。如果使用reserve函数为vec预留内存,就可以节省多次扩张和拷贝。

优化后
std::vector<uint32_t> GetKeyOfMap(const std::map<uint32_t,uint32_t> &map)
{
    std::vector<uint32_t> vec;
    vec.reserve(map.size());
    for(auto &item : map){
        vec.emplace_back(item.first);
    }
    return vec;
}

需要特别说明的是,vector多次扩张带来内存空洞浪费,在未关闭异常处理时,是可以使用操作shrink_to_fit释放掉未使用的内存,以避免内存浪费的。