为我将在std::map中使用的对象数组分配和释放内存的正确方法

Right way to allocate and release memory for array of objects that I will use in a std::map

本文关键字:分配 数组 方法 释放 内存 对象 std map      更新时间:2023-10-16

我有一个多边形集合,我从数据库中检索这些多边形,并希望将其存储在二进制树中以便快速访问。作为一个二叉树,我使用std::map。

我创建了这个解决方案,如下所述,但我认为这是不正确的,因为我没有调用free()来释放malloc()分配的内存。

我的问题:

  1. 如果我只需要插入和访问这个映射的元素,那么使用std::map是否正确?我只想通过他们的ID快速找到几何图形
  2. 在std::map中,我存储指向几何图形的指针,而不是存储几何图形本身。这是个好主意吗?在我尝试存储几何图形之前,但后来我意识到std::map会复制对象,这会产生问题
  3. 在ConvertSpatial2GPC(..)方法中,我创建了gpc_geometry对象,这些对象创建了引用,我在gpc_free_polygon(..)中发布了这些引用。但我无法释放gpc_geometrics对象本身,因为我在那一点上没有对它的引用

我使用以下结构:

typedef struct                      /* Polygon vertex structure          */
{
  double              x;            /* Vertex x component                */
  double              y;            /* vertex y component                */
} gpc_vertex;
typedef struct                      /* Vertex list structure             */
{
  int                 num_vertices; /* Number of vertices in list        */
  gpc_vertex         *vertex;       /* Vertex array pointer              */
} gpc_vertex_list;
typedef struct                      /* Polygon set structure             */
{
  int                 num_contours; /* Number of contours in polygon     */
  int                *hole;         /* Hole / external contour flags     */
  gpc_vertex_list    *contour;      /* Contour array pointer             */
} gpc_polygon;
typedef std::map<long, gpc_polygon*> layer;

我的工作流程如下:

  1. 从数据库加载项目
  2. 调用方法initializeLayer(),返回一个层(请参阅前面的typedef)
  3. 。。。使用图层
  4. 调用方法freeLayer()以释放层使用的内存

用于初始化几何图形对象的代码:

layer initializeLayer() {
    //... database connection code
    //find the count of objects in database
    int count = ...
    //helper object for loading from database
    spatial_obj* sp_obj = NULL;
    //initialize a array to hold the objects
    gpc_polygon* gpc_objects;
    gpc_objects = (gpc_polygon*)malloc(sizeof(gpc_polygon) * count);
    layer myLayer;
    int i = 0;
    //... query database
    while(db.Fetch()) {
        id = db.GetLongData(0);
        db.GetSDO_Object(&sp_obj); //load from database
        db.ConvertSpatial2GPC(sp_obj, &gpc_mullad[i]); //convert polygon to GPC format
        //insert a pair (ID->pointer to the geometry)
        myLayer.insert(layer::value_type(id, &gpc_objects[i]);
        i++;
    }
    return layer;
}

释放层的代码:

void freeLayer(layer myLayer) {
    for (layer::iterator it = myLayer.begin(); it != myLayer.end(); ++it) {
        gpc_free_polygon(it->second); //frees the memory from this geometry object
    }
}

用于释放几何图形对象的代码:

void gpc_free_polygon(gpc_polygon *p)
{
    int c;
    for (c= 0; c < p->num_contours; c++) {
        FREE(p->contour[c].vertex);
    FREE(p->hole);
    FREE(p->contour);
    p->num_contours= 0;
}

我认为我正在使事情变得更加复杂。

我真的不需要std::映射来存储指针。相反,我可以从数据库中询问多边形,这样它们就已经按ID排序了。然后我可以将多边形存储在一个静态结构(数组或向量)中。当我需要根据元素的ID找到它时,我只会使用二进制搜索算法来找到它(无论如何,这是对数时间,就像二进制树使用的搜索算法一样)。

因此,我的方法initializeLayer()将返回一个数组或向量,我将在程序结束时释放它。

编辑:我发现我不必自己实现二进制搜索。有一个这样的类:std::binary_search。链接:二进制搜索算法

第二版:所以,这就是我最终得到的:

对象结构

typedef struct {
    long id;
    gpc_polygon gpc_obj;
} object;

分层结构

typedef std::vector<muld*> layer;

用于初始化几何图形对象的代码:

layer initializeLayer() {
    //... database connection code
    //find the count of objects in database
    int count = ...
    //helper object for loading from database
    spatial_obj* sp_obj = NULL;
    object* object_ptr = NULL;
    layer myLayer;
    myLayer.reserve(count);
    int i = 0;
    //... query database
    while(db.Fetch()) {
        id = db.GetLongData(0);
        db.GetSDO_Object(&sp_obj); //load from database
        object_ptr = new object;
        object_ptr->id = id;
        db.ConvertSpatial2GPC(sp_obj, &object_ptr->gpc_obj);
        myLayer.push_back(object_ptr);
        i++;
    }
    return layer;
}

释放层的代码:

void freeLayer(layer myLayer) {
    for(std::vector<int>::size_type i = 0; i != myLayer.size(); i++) {
        gpc_free_polygon(&myLayer[i]->gpc_obj);
        delete myLayer[i];
    }
}

进行二进制搜索的代码:

我发现std::binary_search只返回是否找到对象。std::lower_bound()救援!

//Create empty object for searching
object* searched_obj = new obj;
object* found_obj = NULL;
searched_obj->id = id;
layer::iterator it;
it = std::lower_bound(myLayer.begin(), myLayer.end(), searched_obj, obj_comparer);
if(it != kiht.end()) {
    found_obj = *it;
    if(found_obj->id != id) {
        //Error!
    }
} else {
    //Error!
}
//Release memory
delete searched_obj;

用于比较对象的函数

bool obj_comparer(object *a, object  *b) {
    return a->id < b->id;
}