Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在本例中,我可以使用共享的PTR吗?_C++_Shared Ptr_Smart Pointers_Weak Ptr - Fatal编程技术网

C++ 在本例中,我可以使用共享的PTR吗?

C++ 在本例中,我可以使用共享的PTR吗?,c++,shared-ptr,smart-pointers,weak-ptr,C++,Shared Ptr,Smart Pointers,Weak Ptr,我有一个简单的事件处理系统,它给了我一些问题。要使用它,我从类EventHandler继承。然后,构造函数在构造时注册每个对象 下面是EventHandler的构造函数: EventHandler::EventHandler() { EventDispatcher::getInstance().registerListener(this); } 这将调用EventDispatcher的registerListener()成员函数,该函数将该事件存储在向量中 void EventDispa

我有一个简单的事件处理系统,它给了我一些问题。要使用它,我从类
EventHandler
继承。然后,构造函数在构造时注册每个对象

下面是
EventHandler
的构造函数:

EventHandler::EventHandler()
{
   EventDispatcher::getInstance().registerListener(this);
}
这将调用
EventDispatcher
registerListener()
成员函数,该函数将该事件存储在向量中

void EventDispatcher::registerListener(EventHandler* listener) 
{
   mListenerList.push_back(listener);
}
void EventDispatcher::registerListener(std::weak_ptr<EventHandler> listener) 
{
   mListenerList.push_back(listener);
}
mLisernerList的位置如下所示:

vector<EventHandler*> mListenerList;
vector<std::weak_ptr<EventHandler>> mListenerList;
结果是,在mButtons中有一个
unique_ptr
s的向量,在mListenerList中有一个指向相同的动态分配按钮对象的原始指针向量。我不希望智能指针和原始指针指向同一个对象

理想情况下,我希望在mButtons中有一个
shared_ptr
s的向量,在mListenerList中有一个
weak_ptr
s的向量,指向动态分配的按钮对象,同时允许EventHandler在创建时注册每个对象。这可能吗?

类事件处理程序{
class EventHandler {
private
    EventHandler(); //make the constructors protected, also in derived when possible

    template<class T, class...Us> //and make this function a friend
    friend std::shared_ptr<EventHandler> make_event(Us...us);
};
//this is the function you use to construct Event objects
template<class T, class...Us>
std::shared_ptr<T> make_event(Us...us)
{
    auto s = std::make_shared<T>(std::forward<Us>(us)...);
    EventDispatcher::getInstance().registerListener(s);
    return s;
}
私有的 EventHandler();//尽可能使构造函数受保护,也在派生中 模板//并使此函数成为朋友 friend std::shared_ptr make_事件(美国…美国); }; //这是用于构造事件对象的函数 模板 std::共享ptr制造事件(美国…美国) { 自动s=std::使_共享(std::转发(美国)…); EventDispatcher::getInstance().registerListener; 返回s; }
这将调用EventDispatcher的registerListener()成员函数,该函数将其存储在向量中

void EventDispatcher::registerListener(EventHandler* listener) 
{
   mListenerList.push_back(listener);
}
void EventDispatcher::registerListener(std::weak_ptr<EventHandler> listener) 
{
   mListenerList.push_back(listener);
}
void EventDispatcher::registerListener(std::弱\u ptr侦听器)
{
mListenerList.push_back(侦听器);
}
mLisernerList的位置如下所示:

vector<EventHandler*> mListenerList;
vector<std::weak_ptr<EventHandler>> mListenerList;
vectormlistenerlist;
EventDispatcher只需对向量的每个元素调用sendEvent(),将事件通知给它

让我举个例子来说明我的问题。假设我的类按钮继承自EventHandler。我将在堆上创建按钮对象,然后在一个向量中放置指向所有按钮的智能指针

vector<unique_ptr<Buttons>> mButtons;   
mButtons.push_back(unique_ptr<Buttons>(new Button()));
vector<std::shared_ptr<Buttons>> mButtons;   
mButtons.push_back(make_event<Buttons>());
向量mButtons;
mButtons.push_back(make_event());

你不能天真地使用
std::shared\u ptr
;有一些特别的 支持可能允许,但过于复杂,以及 在这里几乎肯定不合适;这是不可能的
EventDispatcher
通常会“拥有”一个
EventHandler

这里真正的问题是为什么要使用smart 这里有指针吗?
EventHandler
在其 构造函数,并在其析构函数中取消注册。中的指针
EventDispatcher
纯粹用于导航。同样的事情 可能适用于
mButtons
,尽管有些设计 情况可能并非如此。(我倾向于对这个问题有点怀疑
唯一的向量\u ptr
。它取决于向量的位置 但是从我所看到的,额外的复杂性 访问实际指针所需的时间超过了
手动处理删除。)

这是可能的。您可能想查看
std::enable_shared_from_this
@omnipotential我意识到我需要使用enable_shared_from_this来避免出现问题。虽然这可能是一个更微妙的问题,但我只是在保留EventHandler的当前行为,但将其扩展为共享一个指针时感到困惑。智能指针和原始指针指向同一个对象有什么不对?只要智能指针“拥有”,而原始指针不拥有,@Chris Drew I遵循这个建议,“如果您想充分利用智能指针,您的代码应该避免使用原始指针引用相同的对象;否则很容易出现悬空指针或双重删除的问题…在混合中使用一些内置指针可能会很有用,但前提是您非常小心,如果对象已被删除,它们可能无法使用,并且您永远不会,使用它们删除对象或以其他方式使用它们行使对象的所有权。我的建议是。。。@user870130:IMHO,这是个糟糕的建议。我认为智能指针非常适合“拥有”指针(或者在
弱\u ptr
的情况下“可选地”拥有)但是,当您知道对象将比指针寿命长时,原始指针仍然最适合非所有权指针。智能指针不是银弹,您仍然需要清楚的所有权概念,否则您将遇到问题,可能不是指针悬空或重复删除,而是性能差或内存泄漏。例如,我需要创建一个few堆上的对象以将它们保留在范围内。然后我想将它们保留在一个向量中,这样我就可以导航它们(你是对的)。最后,我有一个我想使用的事件处理程序系统。每个步骤看起来都很简单,逻辑性也很强。但是,在实践中,这似乎会造成混乱。你能建议一个更好的方法吗?名称(特别是
按钮
)建议使用GUI。通常,GUI的组件将属于包含它们的组件;其他组件,如
事件处理程序
(如果不是其中一个GUI组件的基类)将属于它们所服务的类。在某处注册的组件将在其析构函数中取消注册(并且注册将使用原始指针)。因此,每个对象都将属于一个单独的其他对象。您可以使用
unique\ptr
进行此操作,但如果这些对象位于向量中,您可能会发现手动执行必要的删除操作同样容易。