简体   繁体   中英

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.

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.

Have you any solution? Thanks :)

--- EDIT 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). 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.

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*> . Fill it with new and empty it with 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. reserve allocates space for the vector's data, so addresses won't be invalidated unless you push_back more than n points. std::vector::resize could also work but check documentation first as it's slightly different.

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

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

#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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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