如何使用 std::vector 防止内存重新分配
How to prevent memory reallocation using std::vector
我读过很多问题,但没有人回答我的具体案例。
其实我有
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;
};
尽管测量是唯一确定的方法,但基于指针的解决方案中固有的缓存局部性丢失和间接内存访问几乎肯定会导致运行时间慢一个数量级。
两个简单的选项:
-
使用
std::vector<Point*>
. 用new
填充它,然后用delete
清空它。 您的点将存在于堆中,并且当向量增长时,它们不会失效。
在 push_back
点之前,请拨打尺寸n
std::vector::reserve
。reserve
为矢量的数据分配空间,因此除非您push_back
超过n
个点,否则地址不会失效。std::vector::resize
也可以工作,但首先检查文档,因为它略有不同。
编辑:
- 一位评论者提到了保存索引,这是一个好主意,可能比所有这些更简单。
我已经读过关于使用 std::unique_ptr 但我认为不是最好的方法
那么共享指针呢?
我的意思是。。。如果你的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:如果points
的所有元素都存储在一个唯一的顺序区域中并不重要,我建议您考虑使用std::deque
而不是std::vector
- C++ 如何在将新对象分配给另一个对象时创建新对象
- 如何增加以前由新运算符分配的 C++ std::list 数组的大小?
- 为模板参数类型中的新对象分配内存
- 新运算符分配的大小大于声明的大小.为什么
- 在C++中分配分配
- 为什么支撑初始化分配分配填充垃圾变量
- C 新操作员分配新内存
- 新不分配内存?
- 如果我的C++“新”内存分配失败,如何找出返回值
- 我可以用新的分配内存块吗?
- COM / DCOM:服务器存根不会为现有接口中的新方法分配内存
- 在线程在 C++ 中完成后将新任务分配给线程
- 只能使用CUDA中的新运算符分配有限的内存
- 与将新内容分配给向量的指针斗争
- 确定C++中新运算符分配的内存大小
- 按新内存分配
- 是否有必要使用 'new' 将新指针分配给与指向同一结构的先前存在的指针相同的结构?如果是这样,为什么?
- 用于新运算符分配的公共内存
- boost::io_service post方法是否引起新的分配?
- 如何在C++中检索由新运算符分配的对象的地址