【问题标题】:map filled with junk records充满垃圾记录的地图
【发布时间】:2013-03-10 21:26:02
【问题描述】:

我正在使用这样的地图:

map<int,CUser*> m_mUsers;

...

for ( i = m_mUsers.begin(); i != m_mUsers.end(); i++ )
{
    if( (*i).second->GetUserID() == pUser->GetUserID() )
        (*i).second->OnDeviceLogout( pUser );
}

...

添加到地图:

m_mUsers[ sd ] = pUser;

从地图中删除:

i = m_mUsers.find( sd );
m_mUsers.erase( i );

当我运行它时,大多数情况下它都按我的预期工作。但很少有垃圾记录留在地图中,所以当我尝试遍历预期为空的地图时,我遇到垃圾记录,并在 i->second->GetUserID() 上崩溃...什么我做错了吗?

【问题讨论】:

  • 如果iend 怎么办?此外,可能隐藏了一个问题 - 这个pUser 可能会损坏地图中的元素,因为它只是一个指针。
  • 我有一个调试技巧给你。实现一个遍历地图并通过调用一个简单的验证函数来验证每个节点的函数。当您从地图中删除一个节点时,将该节点标记为无效,以便您的验证函数抱怨。然后在您的代码周围散布该验证功能。这样您就可以更快地发现失效并更好地处理根本原因。

标签: c++ stl


【解决方案1】:

您没有检查i != m_mUsers.end()。这是不正确的,除非 保证 sd 在您的情况下存在。

i = m_mUsers.find( sd );

//You should do the check before erasing
if (i != m_mUsers.end()) {
    m_mUsers.erase( i );
}

这应该使代码正常工作。顺便说一句,我建议你使用 std::shared_ptrstd::unique_ptr 用于地图的 mapped_type。 如果您没有可用的 c++11,可以尝试technical reportboost libraries, 其中包括智能指针。 如果你只是想有一个参考而不关心在std::map 中管理CUsers, 您也可以这样做,这意味着您没有为CUsers 管理内存(仅在 c++11 中):

//No room for the question: Who is managing CUser memory in this map?
std::map<int, std::reference_wrapper<CUser>> m_mUsers;

如果你不修改用户,你甚至可以这样做:

//Note I added const to CUser
std::map<int, std::reference_wrapper<CUser const>> m_mUsers;

【讨论】:

  • 我实际上在 debian(gcc 4.4.5) 上,升级到 4.7 似乎太麻烦了,所以我可能会使用 boost 并轻松修改我的代码以删除原始指针的使用。 . 谢谢大家的意见!
  • 顺便说一下,对于gcc 4.4.5,你可以在头文件tr1/utility中使用std::tr1::reference_wrapper。如果您要将代码移植到不支持std::tr1 的编译器,那么您可以坚持使用boost::reference_wrapper 来提升。这些中的任何一个都不需要 c++11。如果你想要智能指针 tr1/memorystd::tr1::shared_ptr 如果你需要的话。没有unique_ptr,那个只有 c++11。因此,根据您是想要可移植性还是依赖 gcc,您可以选择使用 booststd::tr1
猜你喜欢
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多