[英]c++ vector of class object pointers
我要做的基本上是创建两个对象向量,其中一些对象同时输入到两个列表中,而另一些则刚刚输入到一个列表中。 我发现的第一个问题是,当我使用push_back()将一个对象添加到两个列表中时,该对象已被复制,因此当我从一个列表中对其进行更改时,该对象在另一个列表中不会发生变化。 为了解决这个问题,我尝试创建一个指向对象的指针列表作为列表之一。 但是,当我稍后在数据上访问指针时似乎已损坏,则数据成员值都错误。 以下是我的代码片段:
向量的定义:
vector<AbsorbMesh> meshList;
vector<AbsorbMesh*> absorbList;
...向两个对象添加对象:
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
// Add to the absorption list
absorbList.push_back(&nurbsMesh);
// Store the mesh in the scene list
meshList.push_back(nurbsMesh);
访问对象:
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0]->receivedPower;
}
我究竟做错了什么?
缺少一些细节,但这只是一个猜测。
nurbsMesh
在push_back
和absorbList[0]->receivedPower
之间超出范围。
因此,现在您的指针向量包含一个指向不再存在的对象的指针。
尝试将复制构造函数添加到您的AbsorbMesh类中,然后将其添加到向量中。
absorbList.push_back(new AbsorbMesh(nurbsMesh));
meshList.push_back(nurbsMesh);
别忘了像这样删除absorbList
的对象
for(vector<AbsorbMesh*>::iterator it = absorbList.begin(); it != absorbList.end(); it++) {
delete it;
}
或者将共享指针存储在向量中,而不是裸指针。 如果您感兴趣的话,Boost具有良好的共享指针实现。 在这里查看文档
如果要更新一个向量中的项目,而修改另一向量中的对象,则需要在两个向量中存储指针。
使用您的原始要求(更新一个向量中的项目会影响另一向量中的项目,这就是我使用boost共享指针的方式(警告,未经测试的代码)
vector<boost::shared_ptr<AbsorbMesh> > meshList;
vector<boost::shared_ptr<AbsorbMesh> > absorbList;
boost::shared_ptr<AbsorbMesh> nurb = new AbsorbMesh(nurbs.CreateMesh(uStride, vStride));
meshList.push_back(nurb);
absorbList.push_back(nurb);
...
...
if (absorbList.size() > 0)
{
float receivedPower = absorbList[0].get()->receivedPower;
}
您正在存储分配在堆栈上的对象的地址。 只要您的push_back()
结束, nurbsMesh
对象就会被销毁。 如果以后尝试访问此指针,则该对象已被破坏并包含垃圾。 您需要保留即使功能超出范围仍保留的对象。 为此,使用new
为堆中的对象分配内存。 但是对于每一个新的,您都应该有一个相应的delete
。 但是在您的情况下,将同一个指针推入两个向量时,将其删除会遇到问题。 为了解决这个问题,您将需要某种类型引用计数机制。
当您尝试从向量获取指针时,对象被删除。
尝试做
vector.push_back(new Object);
解决了其他人提到的问题(将指针存储到堆栈上的对象)后,您将遇到另一个问题。 vector
可能会重新分配,从而导致其内容移动到另一个位置。
因此,安全的方法是将指针存储在两个向量中。 然后,当然,您需要确保将其删除...但是那是您的C ++。
absorbList.push_back(&nurbsMesh);
是错的
absorbList
保存指向本地对象的指针。 当nurbMesh
被破坏时,您将无法编写absorbList[0]->
但是,当我稍后访问指针时,数据似乎已损坏
当您将某物放在矢量上时,矢量可能会将其从一个物理位置移动到另一个物理位置(尤其是在调整矢量大小时),这会使指向该对象的任何指针无效。
要解决此问题,您需要在两个向量中存储一个指针(可能是“智能指针”)(而不是让一个向量按值包含对象)。
如果要执行此操作,则最好禁用对象的复制构造函数和赋值运算符(通过将它们声明为私有,而不定义它们),以确保在创建对象后不能将其移动。
您的示例有几处错误
AbsorbMesh nurbsMesh = nurbs.CreateMesh(uStride, vStride);
该对象在堆栈上分配。 它是纯本地对象。 当您到达由{}包围的当前块的末尾时,该对象将被销毁。
absorbList.push_back(&nurbsMesh);
现在,您获得了最有可能被破坏的对象的指针。
meshList.push_back(nurbsMesh)
这样就在向量上复制了一个全新的对象。
同样,首先将对象推到向量上,然后使用absorbList.push_back( &meshList.back() )
将指针推到向量上的对象也是错误的,因为vector::push_back
将重新分配整个向量,从而使所有指针无效。
你也许可以创造一切AbsorbMesh
第一对象,把它们到向量,然后拿到指针在矢量这些对象。 只要您不触摸矢量,就可以了。
或者,使用new AbsorbMesh()
在堆上创建对象,但确保对由此创建的每个指针调用delete
。 否则,您将发生内存泄漏。
第三种解决方案,避免麻烦,并使用可帮助您破坏对象的智能指针 。
首先,正如其他人指出的那样,您不能在堆栈上分配对象(即,不是通过new
或类似方法),而是在离开作用域之后将它们放到周围。
其次,将对象放在STL容器中并维护指向它们的指针非常棘手,因为容器可以移动对象。 通常这是一个坏主意。
第三,由于无法复制auto_ptrs,因此auto_ptr<>
根本无法在STL容器中使用。
指向独立分配的对象的指针可以工作,但是在正确的时间删除它们很棘手。
最有效的方法是shared_ptr<>
。 使每个向量成为vector<shared_ptr<AbsorbMesh> >
,并通过new
分配,并且以很少的性能代价就避免了很多麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.