如何使用 std::vector 防止内存重新分配
How to prevent memory reallocation using std::vector
我已经阅读了很多问题,但没有人针对我的具体情况回答我。
其实我有
std::vector<Point2Dd> points;
std::vector<Triangle> triangles;
Point2Dd
是二维点的class,具体如何实现并不重要。
但是三角形的实现方式如下:
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 ---
为了澄清我的问题,我解释了我要解决的问题。
我正在进行增量 Delaunay 三角剖分(没问题)。
所以我必须逐点添加并更新我的三角剖分。
所以我想将三角形作为指向我的点的三指针来管理。我还有一个 dag(Node -> Triangles with three children)和一个保存相邻三角形的结构。
这就是为什么我一直想使用指针,这样我就不必在三个不同的结构中复制相同的点。
这就是为什么我需要解决这个问题以防止内存重新分配。
Yes because after this I've a very heavy algorithm, so I need to optimize all as I can..
在这种情况下,从数据副本开始。
struct Triangle{
Triangle();
Triangle(Point2Dd p1, Point2Dd p2, Point2Dd p3);
// Getter & setter
private:
Point2Dd vA, vB, vC;
};
虽然测量是唯一确定的方法,但基于指针的解决方案中缓存局部性的丢失和间接内存访问几乎肯定会导致 运行 慢一个数量级.
I've read about using std::unique_ptr but I don't think is the best way
那么共享指针呢?
我的意思是...如果您的 Triangle
class 包含三个 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]);
}
p.s.: 如果 points
的所有元素都存储在一个唯一的顺序区域并不重要,我建议你考虑使用 std::deque
而不是std::vector
两个简单的选项:
使用 std::vector<Point*>
。用 new
填充,用 delete
清空。您的积分将保存在堆上,并且不会随着向量增长而失效。
在 push_back
点之前调用 std::vector::reserve
大小 n
。 reserve
为矢量数据分配 space,因此除非您 push_back
超过 n
点,否则地址不会失效。 std::vector::resize
也可以,但请先查看文档,因为它略有不同。
编辑:
- 一位评论者提到保存索引是个好主意,可能比所有这些都简单。
我已经阅读了很多问题,但没有人针对我的具体情况回答我。
其实我有
std::vector<Point2Dd> points;
std::vector<Triangle> triangles;
Point2Dd
是二维点的class,具体如何实现并不重要。
但是三角形的实现方式如下:
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 ---
为了澄清我的问题,我解释了我要解决的问题。 我正在进行增量 Delaunay 三角剖分(没问题)。 所以我必须逐点添加并更新我的三角剖分。
所以我想将三角形作为指向我的点的三指针来管理。我还有一个 dag(Node -> Triangles with three children)和一个保存相邻三角形的结构。
这就是为什么我一直想使用指针,这样我就不必在三个不同的结构中复制相同的点。
这就是为什么我需要解决这个问题以防止内存重新分配。
Yes because after this I've a very heavy algorithm, so I need to optimize all as I can..
在这种情况下,从数据副本开始。
struct Triangle{
Triangle();
Triangle(Point2Dd p1, Point2Dd p2, Point2Dd p3);
// Getter & setter
private:
Point2Dd vA, vB, vC;
};
虽然测量是唯一确定的方法,但基于指针的解决方案中缓存局部性的丢失和间接内存访问几乎肯定会导致 运行 慢一个数量级.
I've read about using std::unique_ptr but I don't think is the best way
那么共享指针呢?
我的意思是...如果您的 Triangle
class 包含三个 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]);
}
p.s.: 如果 points
的所有元素都存储在一个唯一的顺序区域并不重要,我建议你考虑使用 std::deque
而不是std::vector
两个简单的选项:
使用
std::vector<Point*>
。用new
填充,用delete
清空。您的积分将保存在堆上,并且不会随着向量增长而失效。在
push_back
点之前调用std::vector::reserve
大小n
。reserve
为矢量数据分配 space,因此除非您push_back
超过n
点,否则地址不会失效。std::vector::resize
也可以,但请先查看文档,因为它略有不同。
编辑:
- 一位评论者提到保存索引是个好主意,可能比所有这些都简单。