取消引用指向不再存在的框架的指针
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
。
我有 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
。