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

How to prevent memory reallocation using std::vector

本文关键字:新分配 分配 std 何使用 vector 内存      更新时间:2023-10-16

我读过很多问题,但没有人回答我的具体案例。

其实我有

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

Point2Dd是 2D 点的类,指定其实现方式并不重要。

然而,三角形的实现方式如下:

class Triangle{
public:
Triangle();
Triangle(Point2Dd* p1, Point2Dd* p2, Point2Dd* p3);
// Getter & setter
private:
Point2Dd* vA = nullptr;
Point2Dd* vB = nullptr;
Point2Dd* vC = nullptr;
}

也就是说,作为点向量的三分球。

实际上它工作得很好,但我想过:如果我在我的向量中添加另一个点并且我的向量会改变所有内存地址?我所有的三角形都将由无效地址组成。

我已经读过关于使用std::unique_ptr<Point2Dd>但我认为不是最好的方法。

你有什么解决方案吗? 谢谢:)

--- 编辑 1 ---

为了澄清我的问题,我解释了我试图解决的问题。 我正在做一个增量的德劳内三角测量(没问题(。 所以我必须逐点添加一次并更新我的三角测量。

所以我认为将三角形管理为指向我点的三指针。我还有一个 dag(节点 -> 有三个孩子的三角形(和一个保存相邻三角形的结构。

这就是为什么我想总是使用指针,所以我不必在三个不同的结构中复制相同的点。

这就是为什么我需要解决这个问题以防止内存重新分配。

是的,因为在此之后我有一个非常繁重的算法,所以我需要尽可能地优化所有算法。

在这种情况下,请从数据副本开始。

struct Triangle{
Triangle();
Triangle(Point2Dd p1, Point2Dd p2, Point2Dd p3);
// Getter & setter
private:
Point2Dd vA, vB, vC;
};

尽管测量是唯一确定的方法,但基于指针的解决方案中固有的缓存局部性丢失和间接内存访问几乎肯定会导致运行时间慢一个数量级。

两个简单的选项:

  1. 使用std::vector<Point*>. 用new填充它,然后用delete清空它。 您的点将存在于堆中,并且当向量增长时,它们不会失效。

  2. push_back点之前,请拨打尺寸nstd::vector::reservereserve为矢量的数据分配空间,因此除非您push_back超过n个点,否则地址不会失效。std::vector::resize也可以工作,但首先检查文档,因为它略有不同。

编辑:

  1. 一位评论者提到了保存索引,这是一个好主意,可能比所有这些更简单。

我已经读过关于使用 std::unique_ptr 但我认为不是最好的方法

那么共享指针呢?

我的意思是。。。如果你的Triangle类包含三个std::shared_ptr<Point2Dd>,而不是三个旧样式的指针,如果pointsstd::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:如果points的所有元素都存储在一个唯一的顺序区域中并不重要,我建议您考虑使用std::deque而不是std::vector