取消引用指向不再存在的框架的指针

Dereferencing a pointer to a frame that doesn't exist anymore

我有 MessagesViewer 个框架,我想控制其唯一性,

用这段代码:

MessagesViewer* m_pMsgViewer = NULL;

void Application::ShowMessagesViewer()
{
    if (m_pMsgViewer == NULL)
    {
        m_pMsgViewer = new MessagesViewer(
            wxGetApp().GetContainer()->GetAppData()->GetMessages()
        );
    }
    else
    {
        m_pMsgViewer->FillPage(wxGetApp().GetContainer()->GetAppData()->GetMessages());
        m_pMsgViewer->SetFocus();
    }
}

但是当我第一次调用它时,m_pMsgViewer 开始引用内存中的有效数据。当我关闭 MessagesViewer 框架时,它会自动销毁它,但指针仍指向旧地址,我无法控制从该客户端代码销毁框架。

如何取消对指向已销毁框架的指针的引用?

您需要以某种方式标记 MessagesViwer 已被销毁且无法再被引用。这意味着除了 m_pMsgViewer.

之外还有一些额外的信息

一种解决方案是在 MessagesViewer 关闭时将 m_pMsgViewer 设置回 nullptr。一种安全的方法是将 wxEVT_CLOSE_WINDOW 的处理程序添加到您的框架中。例如,将以下代码添加到 MessagesViewer 的构造函数中:

Bind(wxEVT_CLOSE_WINDOW, [](wxCloseEvent& evt)
{
   m_pMsgViewer = nullptr;
   evt.Skip();
});

evt.Skip() 让事件进一步传播到 wx 提供的默认处理程序。

这个简单的例子假定 m_pMsgViewer 是一个全局变量。如果它实际上包含在 Application 对象中,则您必须添加一些方法来访问它。


将此类代码添加到 MessagesViewer 析构函数 的明显替代方案并不是一个好主意,因为 MessagesViewer 对象的实际销毁已延迟 according to the docs,因此理论上 Application::ShowMessagesViewer() 可以在已关闭并标记为销毁但尚未实际销毁的框架上调用 FillPage()

处理关闭事件会提前重置指针,从而避免上述问题。

@bogdan 已经提出了一个很好的解决方案,但还有另一个更自动的解决方案:将您的帧指针存储在 wxWeakRef<> 中。 IE。保持与现在完全相同的代码,但将声明替换为

wxWeakRef<MessagesViewer> m_pMsgViewer;

当window被销毁时,弱引用会自动重置为NULL