【发布时间】:2014-05-06 16:54:05
【问题描述】:
我有一个简单的事件处理系统,它给我带来了问题。为了使用它,我继承自 EventHandler 类。然后构造函数在构造时注册每个对象。
这是EventHandler的构造函数:
EventHandler::EventHandler()
{
EventDispatcher::getInstance().registerListener(this);
}
这会调用EventDispatcher 的registerListener() 成员函数,该函数将其存储在向量中。
void EventDispatcher::registerListener(EventHandler* listener)
{
mListenerList.push_back(listener);
}
mLisernerList 长这样在哪里:
vector<EventHandler*> mListenerList;
EventDispatcher 只需在向量的每个元素上调用 sendEvent() 即可将事件通知它。
让我举个例子来说明我的问题。假设我的类Buttons 继承自EventHandler。我将在堆上创建按钮对象,然后将指向所有按钮的智能指针放在一个向量中。
vector<unique_ptr<Buttons>> mButtons;
mButtons.push_back(unique_ptr<Buttons>(new Button()));
我最终会在 mButtons 中得到一个 unique_ptrs 向量,在 mListenerList 中得到一个指向相同动态分配的 Button 对象的原始指针向量。我不希望智能指针和原始指针指向同一个对象。
理想情况下,我希望 mButtons 中的 shared_ptrs 向量和 mListenerList 中的 weak_ptrs 向量指向动态分配的 Button 对象,同时允许 EventHandler 在创建时注册每个对象。这可能吗?
【问题讨论】:
-
有可能。你可能想看看
std::enable_shared_from_this -
@OmnipotentEntity 我意识到我需要使用 enable_shared_from_this 来避免这个问题。虽然这可能是更微妙的问题,但我只是难以保持 EventHandler 的当前行为,但将其扩展为共享指针。
-
智能指针和原始指针指向同一个对象有什么问题?只要智能指针“拥有”而原始指针没有。
-
@Chris Drew 我遵循了这个建议,“如果你想获得智能指针的全部好处,你的代码应该避免使用原始指针来引用相同的对象;否则太容易拥有悬空指针或双重删除的问题......混合使用一些内置指针可能很有用,但前提是你非常小心,如果它们的对象已被删除,它们就不可能被使用,而且你永远不会,使用它们来删除对象或以其他方式与它们一起行使对象的所有权。我的建议是......永远不要混合它们。”
-
@user870130:恕我直言,这是个坏建议。我认为the conventional wisdom from gurus like Herb Sutter 是智能指针非常适合“拥有”指针(或在
weak_ptr的情况下“可选地”拥有),但是当您知道对象将存活时,原始指针仍然最适合非拥有指针指针。智能指针不是灵丹妙药,您仍然需要清楚地了解所有权,否则您会遇到问题,可能不是悬空指针或双重删除,而是性能不佳或内存泄漏等问题。
标签: c++ shared-ptr smart-pointers weak-ptr