我在一个管理器内的基类的指针向量中有一组对象:
std::vector<object*> objectVec;
类可能希望使用管理器中的Add()方法生成其中一个对象。问题是他们随后需要自己设置或更新这些对象。我决定让Add()返回一个指向对象本身的指针,该指针存储在决定产生一个的任何类中。问题是处理指针后面的对象可能已被删除的情况。
添加如下所示:
object* ObjectManager::Add(object* obj)
{
objectVec.push_back(obj);
return objectVec.back();
}
并像这样使用:
objectptr = ObjectManager::OMan()->Add(new object());
其中objectptr是调用该函数的任何类的成员。因此,如果要删除该特定对象,Add返回的指针将指向垃圾。
如果删除此对象,是否有责任确保whateverclass :: objectptr始终设置为NULL?或者可以使用某种智能指针处理?问题是我不需要使用智能指针来处理内存泄漏的可能性,而是处理存储指针变为无效的情况。
如果我不清楚,或者问题是否形成错误,请告诉我。
非常感谢任何帮助。
答案 0 :(得分:3)
是的,你可以在你的载体中存储智能ptr而不是原始ptr。在这种情况下,如果有人释放了一个对象,那么在最后一个引用未释放之前它不会被删除(在你的情况下,在向量中保存一个引用)。您可以使用boost::shared_ptr
或std::shared_ptr
(C ++ 11)。
如果这不是您想要的,您可以使用boost::weak_ptr
在向量中存储引用。 weak_ptr
不会增加引用计数器,所以如果某人释放了一个对象,它就会被删除,但是你的向量中存储的引用(weak_ptr)允许你检查它。
答案 1 :(得分:2)
你可能想要weak_ptr和shared_ptr。 shared_ptr是一般智能指针类。 weak_ptr是shared_ptr的观察者。当shared_ptr的所有引用消失时,weak_ptr的实例“变为null”并且比指向已删除对象的指针更容易处理。
这些课程附带Boost。 http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm
http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/weak_ptr.htm
如果我没弄错的话,在实现更新的C ++ 0x标准的编译器上有std命名空间内置的等价物。 Visual C ++ keep内置了这个。
http://blogs.msdn.com/b/vcblog/archive/2011/02/16/10128357.aspx
哦,拍摄,看起来像其他人一样打败我的答案......答案 2 :(得分:2)
最好是忘记这个“经理”的想法,但如果你这样做,或者如果你不这样做,共享所有权的解决方案就像往常一样,使用boost::shared_ptr
。
或者,使用相对较新的编译器,使用std::shared_ptr
。
考虑到shared_ptr
所有权问题已经得到解决,那么问问自己,“经理”管理的是什么?
干杯&amp;第h。,
答案 3 :(得分:1)
如果此对象被删除,我是否有责任确保
whateverclass::objectptr
始终设置为NULL
?
你正在上课,所以由你来决定。这是一项设计决定,只要您记录它,就可以接受这两种选择:
或者可以使用某种智能指针来解决这个问题吗?
使用智能指针(强或弱版本)将有助于实现您为课程选择的任何行为。但是,它也会强烈影响客户端代码。在以下代码中:
class Scene
{
// can't use this object in a call to `ObjectManager::Add()`,
// assuming it uses a smart pointer to deal with object lifetimes.
Object myLight;
};
除了实现的简单性之外,还应考虑ObjectManager
类的用例。想想“写一次,多用”。
答案 4 :(得分:0)
悬空指针和内存泄漏是两个不同的问题,但正确的共享指针可以保护两者。对于这种特殊情况,我建议boost::shared_ptr
。
使用std::vector<boost::shared_ptr<BaseType>>
作为矢量类型,并且现在保持裸指针的对象代替boost::shared_ptr<BaseType>
。这将确保指针在vector
和对象中保持有效,只要其中一个对象仍然存在。
如果您有不同的要求,可以在其中一个拿着指针的地方(boost::weak_ptr
或对象)使用vector
。
此外,对象可以保存派生类型而不是基本类型(boost::shared_ptr<DerivedType>
),您可以使用boost::shared_static_cast
在它们之间进行转换。