繁体   English   中英

类对象指针的C ++向量

[英]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;
}

我究竟做错了什么?

缺少一些细节,但这只是一个猜测。

nurbsMeshpush_backabsorbList[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM