我正在不同系统之间转换一些代码,我有一个关于 c++ vector 的问题。
如果我这样做:
在头文件中:
struct Vertex
{
float x;
float y;
float z;
}
struct submesh
{
Vertex *meshdata;
}
std::vector<submesh> meshes;
在c++文件中的例程中:
{
Vertex *data = new Vertex[1024];
submesh g;
g.meshdata = data;
meshes.push_back(g);
delete [] data;
}
我会遇到麻烦吗?我的假设是,一旦我对其调用 delete,该 vector 将包含一个指向不再有效的数据的指针。我是否需要为 Vertex 编写复制构造函数以便首先复制数据?
附加:
问题更多是关于如何将指向已分配内存的指针放入 std::vector<> 并仍然清理本地分配的数据。本质上,我如何将数据复制到 vector 中,以便我仍然可以清理我的拷贝。
原始代码在 DirectX 中。我正在将它移植到 iPhone。原始代码在例程中使用以下方式在本地分配子网格:
{
ID3DXMesh* subMesh = 0;
D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS, D3DXMESH_MANAGED, elems, gd3dDevice, &subMesh));
//
// ... do some magical things to submesh
//
SubGrid g;
g.mesh = subMesh;
g.box = bndBox;
mSubGrids.push_back(g);
}
我试图复制如何将 ID3DXMesh 添加到 vector ,然后在例程中失去它的范围。
由于我无权访问 D3DXCreateMesh(),我想我会简单地分配我需要的顶点,将它们放入 vector 中,然后清理。
抱歉,我不想透露细节,因为问题很简单,我如何分配数据 block ,将指针放入 std::vector<>,然后清理本地分配的内存. :)
我假设必须在某处编写一个复制构造函数。只是不确定在哪里或如何。
子网格如下所示:
struct SubGrid
{
ID3DXMesh* mesh;
AABB box;
// For sorting.
bool operator<(const SubGrid& rhs)const;
const static int NUM_ROWS = 33;
const static int NUM_COLS = 33;
const static int NUM_TRIS = (NUM_ROWS-1)*(NUM_COLS-1)*2;
const static int NUM_VERTS = NUM_ROWS*NUM_COLS;
};
他们添加到的 vector 看起来像:
std::vector<SubGrid> mSubGrids;
最佳答案
不要在不需要时直接动态分配,在这种情况下您不需要。由于您要填充自己的子网格数据而不是使用 ID3DXMesh
,因此该数据的容器应该符合 RAII。如果我正在编写这个代码,我会完全删除 submesh
类并只使用:
// vector containing list of vertices.
typedef std::vector<Vertex> SubMesh;
您的 SubGrid
类可以成为一个简单的容器,作为其属性之一,它包含一个 submesh
集合。我注意到您还有一个用于盒子对象的 AABB
类。您将继续将其保留在 SubGrid
中。我不必在这里工作,所以我正在制作其中的一些内容,但类似于以下内容:
// a simple 3-value triplet of floats
struct Vertex
{
float x,y,z;
};
// a Submesh is an arbitrary collection of Vertex objects.
typedef std::vector<Vertex> SubMesh;
// I'm defining AABB to be an 8-vertex object. your definition
// is likely different, but I needed something to compile with =)
typedef Vertex AABB[8];
class SubGrid
{
public:
SubGrid() {};
// comparator for container ordering
bool operator <(const SubGrid&);
// submesh accessors
void setSubmesh(const SubMesh& mesh) { submesh = mesh;}
SubMesh& getSubmesh() { return submesh; }
const SubMesh& getSubmesh() const { return submesh; }
// box accessors
AABB& getBox() { return box; }
const AABB& getBox() const { return box;}
private:
SubMesh submesh;
AABB box;
};
// arbitrary collection of SubGrid objects
typedef std::vector<SubGrid> SubGrids;
将此添加到全局 SubGrid
集合 g
时,您有多种可能性。你可以这样做:
// declared globally
Subgrids g;
// in some function for adding a subgrid item
SubGrid subgrid;
AABB& box = subgrid.getBox();
SubBesh& submesh = subgrid.getSubmesh();
// ... initialize your box and submesh data ...
g.push_back(subgrid);
但是您会复制大量数据。要加强内存访问,您总是可以这样做:
// push an empty SubGrid first, then set it up in-place
g.push_back(SubGrid());
Subgrid& subgrid = *(g.back());
AABB& box = subgrid.getBox();
SubMesh& submesh = subgrid.getSubmesh();
//... initialize your box and submesh data ...
这将建立对刚刚添加到全局集合的 SubGrid
的引用,然后允许您就地修改它。这只是许多可能的设置选项之一。应该注意的是,如果你的工具链中有 C++11(如果你在 MacOS 或 iOS 上这样做,你可能会这样做,因为 Apple LLVM 4.2 的 clang 在 C++11 合规性方面非常好)这个明智地使用移动构造函数 和移动赋值运算符 可以获得更高的效率。
最重要的是,不会看到new
或delete
。
无论如何,我希望这能给你一些想法。
关于c++ - 将指针插入 C++ vector 并进行清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14796670/