简体   繁体   English

如何使用std :: vector防止内存重新分配

[英]How to prevent memory reallocation using std::vector

I've read a lot of question but no one answer me for my specific case. 我读了很多问题,但没人回答我的具体情况。

Actually I have 其实我有

std::vector<Point2Dd> points;
std::vector<Triangle> triangles;

Point2Dd is a class for a 2D point, it is not important to specify how it is implemented. Point2Dd是2D点的类,指定其实现方式并不重要。

Triangle however is implemented like: 但是,三角形的实现方式如下:

class Triangle{
    public:
     Triangle();
     Triangle(Point2Dd* p1, Point2Dd* p2, Point2Dd* p3);
     // Getter & setter

    private:
     Point2Dd* vA = nullptr;
     Point2Dd* vB = nullptr;
     Point2Dd* vC = nullptr;
}

that is, as three-pointers to vector of points. 即作为点向量的三指针。

Actually it work perfectly but I've think: if I add an other point into my vector and my vector change all memory address? 实际上,它可以正常工作,但我认为:如果我在向量中添加了另一个点,而向量又更改了所有内存地址? All my triangles will be composed by invalid address. 我所有的三角形将由无效地址组成。

I've read about using std::unique_ptr<Point2Dd> but I don't think is the best way. 我已经读过有关使用std::unique_ptr<Point2Dd>但我认为这不是最好的方法。

Have you any solution? 你有什么解决办法吗? Thanks :) 谢谢 :)

--- EDIT 1 --- -编辑1-

To clarify my problem I explain what problem I'm trying to solve. 为了澄清我的问题,我解释了我要解决的问题。 I'm doing an incremental Delaunay Triangulation (no problem with that). 我正在做增量Delaunay三角剖分(没问题)。 So I have to add once by once a point and update my triangulation. 因此,我必须一次添加一个点并更新三角剖分。

So I've think to manage triangle as a three pointer to my points. 因此,我认为将三角形作为指向我的观点的三个指针来进行管理。 Also I have a dag (Node -> Triangles with three children) and a structure that save adjacent triangles. 我也有一个dag(节点->有三个子代的三角形)和一个保存相邻三角形的结构。

This is why I've thinked to use always a pointer, so I don't have to copy in three different structures the same points. 这就是为什么我一直考虑使用指针的原因,所以我不必在三个不同的结构中复制相同的点。

This is why I need to solve this problem to prevent memory reallocation. 这就是为什么我需要解决此问题以防止内存重新分配的原因。

Yes because after this I've a very heavy algorithm, so I need to optimize all as I can.. 是的,因为在此之后,我的算法非常繁琐,因此我需要尽一切可能进行优化。

In this case, start with copies of data. 在这种情况下,请从数据副本开始。

struct Triangle{
     Triangle();
     Triangle(Point2Dd p1, Point2Dd p2, Point2Dd p3);
     // Getter & setter

    private:
     Point2Dd vA, vB, vC;
};

Although measurement is the only way to know for sure, the loss of cache locality and the indirect memory access inherent in a pointer-based solution is almost certain to result in run times an order of magnitude slower. 尽管测量是唯一可以肯定的方法,但是基于指针的解决方案固有的缓存局部性损失和间接内存访问的损失几乎可以肯定会导致运行时间降低一个数量级。

Two simple options: 两个简单的选择:

  1. Use an std::vector<Point*> . 使用std::vector<Point*> Fill it with new and empty it with delete . new填充它,并用delete清空它。 Your points will live on the heap and they won't be invalidated when the vector grows. 您的点将保留在堆中,并且当向量增加时它们不会失效。

  2. Call std::vector::reserve with size n before you push_back the points. 在点push_back之前,调用大小为n std::vector::reserve reserve allocates space for the vector's data, so addresses won't be invalidated unless you push_back more than n points. reserve为向量的数据分配空间,因此,除非push_back超过n个点,否则地址不会无效。 std::vector::resize could also work but check documentation first as it's slightly different. std::vector::resize也可以工作,但请先检查文档,因为它略有不同。

Edit: 编辑:

  1. A commenter mentioned saving indices which is a great idea and probably simpler than all of this. 有评论者提到保存索引是个好主意,而且可能比所有这些都简单。

I've read about using std::unique_ptr but I don't think is the best way 我读过有关使用std :: unique_ptr的信息,但我认为这不是最好的方法

And what about shared pointers ? 那共享指针呢?

I mean... if your Triangle class contains three std::shared_ptr<Point2Dd> , instead of three old style pointers, and if points is a std::vector<std::shared_ptr<Point2Dd>> instead of a vector of Points2Dd , you should able to write something as the following example 我的意思是......如果你的Triangle类包含三个std::shared_ptr<Point2Dd>而不是三个旧风格的指针,如果points是一个std::vector<std::shared_ptr<Point2Dd>>替代的载体Points2Dd ,您应该可以编写以下示例

#include <memory>
#include <vector>

struct Point2Dd
 { };

class Triangle
 {
   private:
      using sp2Dd = std::shared_ptr<Point2Dd>;

      sp2Dd vA, vB, vC;

   public:
      Triangle()
       { }

      Triangle (sp2Dd const & p1, sp2Dd const & p2, sp2Dd const & p3)
         : vA{p1}, vB{p2}, vC{p3}
       { }
 };

int main ()
 {
   std::vector<std::shared_ptr<Point2Dd>> points;
   std::vector<Triangle>                  triangles;

   points.emplace_back(new Point2Dd{}); // or using std::make_shared(),
   points.emplace_back(new Point2Dd{}); // if C++14 is available
   points.emplace_back(new Point2Dd{});

   triangles.emplace_back(points[0U], points[1U], points[2U]);
 }

ps: if isn't important that all the element of points are stored in a unique sequential area, I suggest you to consider the use of std::deque instead of std::vector ps:如果将points所有元素存储在唯一的顺序区域中并不重要,建议您考虑使用std::deque而不是std::vector

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM