Memory management std::vector、std::map和内存问题
我正在编写将数据库中的行插入向量的代码。然后将向量存储在std::map中。这种体系结构允许我基于映射键对数据集(向量)进行逻辑分区 在我的代码中,我将从std::map中检索一个数据集(即向量),向其中添加/删除行或对其执行一些其他逻辑,然后将向量粘贴回map中(所有这些都在while()循环中进行) 我有两个问题,这两个问题都与向量中存储的(可能)大量元素有关。向量可以包含几十到几万个元素。我无法事先知道将从数据库中检索多少条记录。因此,std::vector的内存管理方案(即alloc/Dealoc)变得非常重要,以便有效地使用内存,并避免不必要的(内存)碎片: 我的问题是:Memory management std::vector、std::map和内存问题,memory-management,stl,vector,map,Memory Management,Stl,Vector,Map,我正在编写将数据库中的行插入向量的代码。然后将向量存储在std::map中。这种体系结构允许我基于映射键对数据集(向量)进行逻辑分区 在我的代码中,我将从std::map中检索一个数据集(即向量),向其中添加/删除行或对其执行一些其他逻辑,然后将向量粘贴回map中(所有这些都在while()循环中进行) 我有两个问题,这两个问题都与向量中存储的(可能)大量元素有关。向量可以包含几十到几万个元素。我无法事先知道将从数据库中检索多少条记录。因此,std::vector的内存管理方案(即alloc/D
using namespace std;
map<string, vector<int>* > foo;
vector<int>* pointer= foo["thekey"];
使用名称空间std;
map foo;
向量*指针=foo[“thekey”];
如果需要使用智能(引用计数)指针:
#include<tr1/shared_ptr.h>
using namespace std::tr1;
using namespace std;
map<string, shared_ptr<vector<int> > > foo;
shared_ptr<vector<int> > pointer= foo["thekey"];
#包括
使用名称空间std::tr1;
使用名称空间std;
map foo;
共享的指针=foo[“thekey”];
为了回答问题#1,您可以编写一个新的分配器模板类并声明向量以使用该分配器,但我对编写分配器一无所知:
map<string, vector<int, myallocator<int> >* > foo;
map-foo;
特别是,我不知道如何设计一个分配器来避免内存池的碎片化。(但如果您已回答了该部分,那么编写自定义分配器将是一种方法。)假设您对地图的
数据类型使用矢量
,而不是键类型
,则可以在不复制数据的情况下就地修改数据std::map::operator[]()
返回对非常量数据类型的引用,并且从非常量版本的std::map::find()
返回的迭代器允许您修改数据
如果在更改数据时需要更改密钥,该怎么办?您可以使用std::swap()
将数据从一个向量移动到另一个向量,而无需复制
不要忘记,当您擦除元素时,vector
不会降低其容量()。另外,vector
通常会分配比您需要的更多的capacity()
,因此push_back()
需要摊销的固定时间。对于非常大的向量,如果不小心,这些行为可能会显著增加程序的内存使用
如果您对地图的键类型使用向量
,并且地图的键非常大,那么指针或智能指针可能会有所帮助。但是,如果是这种情况,则必须确保不要修改其中一个映射值所指向的键的内容,因为std::map
不是为处理该问题而设计的
至于自定义分配器的想法,首先让您的代码使用标准分配器,然后看看它是否足够快。使用标准分配器可能没问题。如果您的代码在使用标准分配器时速度不够快,请配置文件以查看实际花费的时间(可能在其他地方,如数据库代码)。如果您编写了一个自定义分配器,并且从未将其与标准分配器进行比较,那么您将不知道您的自定义分配器是否真的是一种改进;它可能比标准的分配器慢得多。Wrt#1,GCC/Linux(ptmalloc)中的默认堆实现将为小对象使用一个空闲列表(又称内存池)(我将建议一种更通用的方法来处理C/C++中的数据库查询集
执行db查询并将行放入结构数组中。如果没有足够的物理内存,请使用内存映射文件,该文件将返回指向结构数组底部的指针,处理器芯片上的MMU将在需要时担心这些结构会驻留在内存中
现在,您可以在一个键上对这个结构数组进行排序(),这将为您提供ISAM访问,关系宗教中的异端邪说,但这正是游标给您的。这是数据访问方法#1
现在,如果您仍然需要以另一种方式查看该数据,只需创建一个或多个索引/映射,其中映射的键是适当的(列值/结构成员)映射的数据值是指向该结构在内存映射文件中的位置的指针。这提供了与db索引完全相同的功能。通过struct.member值订阅映射