我要做的是基本上创建两个对象向量,其中一些对象输入到两个列表中,一些对象只是输入一个。我发现的第一个问题是,当我使用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;
}
我做错了什么?
答案 0 :(得分:9)
缺少一些细节,但猜测一下。
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有一个很好的共享指针实现。请参阅文档here
如果您希望对另一个向量中的一个向量修改对象中的项进行更新,则需要在两个向量中存储指针。
使用原始要求(更新一个向量中的项目会影响另一个向量中的项目,以下是使用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;
}
答案 1 :(得分:6)
您正在存储堆栈上分配的对象的地址。只要nurbsMesh
的方法结束,push_back()
对象就会被销毁。如果您之后尝试访问此指针,则该对象已被销毁并包含垃圾。您需要的是保留即使在功能超出范围后仍然存在的对象。为此,使用new
从堆中为对象分配内存。但对于每一个新的你应该有一个相应的delete
。但是在你的情况下,当你将相同的指针推入两个向量时,你会有删除它的问题。要解决这个问题,您需要一些类型引用计数机制。
答案 2 :(得分:2)
尝试从向量中获取指针时删除对象。
尝试做
vector.push_back(new Object);
答案 3 :(得分:2)
一旦你解决了其他人提到的问题(存储指向堆栈中对象的指针),你就会遇到另一个问题。 vector
可以重新分配,这会导致其内容移动到另一个位置。
然后,安全的方法是将指针存储在两个向量中。然后,当然,你需要确保它们被删除......但那是你的C ++。
答案 4 :(得分:1)
absorbList.push_back(&nurbsMesh);
错了
absorbList
保存指向本地对象的指针。当nurbMesh
被摧毁时,你无法写
absorbList[0]->
答案 5 :(得分:1)
然而,当我稍后访问指针时,数据似乎已损坏
当你在矢量上放置某个东西时,矢量可能会将它从一个物理位置移动到另一个物理位置(特别是例如调整矢量大小时),这会使指向该对象的指针无效。
要解决此问题,您需要在两个向量中存储指针(可能是“智能指针”)(而不是让一个向量按值包含对象)。
如果您要这样做,最好禁用对象的复制构造函数和赋值运算符(通过将它们声明为私有,而不是定义它们)以确保在创建对象后它不能是移动。
答案 6 :(得分:1)
您的示例有几个问题
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
。否则你有内存泄漏。
第三种解决方案,避免麻烦并使用smart pointers来处理对象破坏。
答案 7 :(得分:1)
首先,正如其他人所指出的那样,你不能在堆栈上分配对象(即,不是new
或类似的东西),并在离开范围后将它们放在一边。
其次,在STL容器中拥有对象并保持指向它们的指针是棘手的,因为容器可以移动东西。这通常是一个坏主意。
第三,auto_ptr<>
在STL容器中不起作用,因为无法复制auto_ptrs。
指向独立分配对象的指针有效,但在正确的时间删除它们很棘手。
最有效的方法是shared_ptr<>
。将每个向量设为vector<shared_ptr<AbsorbMesh> >
,通过new
进行分配,并且在性能上略有降低,可以避免很多麻烦。