【问题标题】:Delete a pointer as first key of std::map删除指针作为 std::map 的第一个键
【发布时间】:2015-06-24 10:49:15
【问题描述】:

我想知道如何正确删除作为std::map 的第一个键的指针。我只能为第二个键解决这个问题。第一个键是只读的。

例子:

std::map<char*,foo> myMap;
char* str = new char[3];
foo bar;
str[0]='h';
str[1]='i';
str[2]='\0';
myMap[str] = bar

/* some code */
for(auto element: myMap)
{
    delete [] element.first;
}

这似乎并没有释放指针。 std::map 是否在某处丢失了指针? 我正在研究大数据,所以我需要尽可能轻的字符串结构。这就是为什么我使用char* 而不是std::string(给地图提供了一个比较函子)。

编辑

为了更精确:

  • 我正在阅读 ADN 序列。对于我正在阅读的每个模式,我将其位置放在地图中。(std::map>)
  • 我正在使用 char*,因为 std::string 分配的 char 数量超过了所需数量
  • 我的首要任务不是计算时间,而是内存空间。

我希望这能帮助你理解我的问题。

【问题讨论】:

  • 您确定您没有过早优化吗?你怎么知道一旦你把你需要的所有工作都投入到使用 char* 中,你就不会回到字符串的开销上?
  • 你为什么说it does not seem to work。什么情况下不起作用
  • 只需使用std::map&lt;std::string, foo&gt;
  • "这似乎没有释放指针。" - 你为什么这么说?它删除数组,在地图中留下一个悬空指针。我不敢想为什么你认为这可能是个好主意;只需使用std::string。或者unique_ptr&lt;char[]&gt;,如果你真的认为你需要尽可能轻的类型来管理动态数组。
  • 你所说的“第一把钥匙”就是钥匙。你所说的“第二个键”就是键对应的值。

标签: c++ pointers c++11 stl stdmap


【解决方案1】:

您的代码已经可以运行(但不是异常安全的——智能指针可以)。请注意,当内存为deleted 时,程序通常不会浪费时间更改它,它只是更改一些空闲/正在使用的记录,因此未来的分配可以考虑重用该内存,因此如果您尝试取消引用 @ 987654322@d 指针你有未定义的行为,但它似乎仍然有旧的内容 - 至少有一段时间。我想这就是你认为释放不起作用的原因......

【讨论】:

  • 我知道这一点。我说 它似乎不起作用 因为 valgrind:1,520 bytes in 304 blocks are definitely lost in loss record 7 of 7 ==7859== at 0x40278F4: operator new[](unsigned int) (vg_replace_malloc.c:343) ==7859== by 0x804CB45: getMerFromSeq(...
  • @Atouk 和 getMerFromSeq 中有什么?作为健全性检查,您可以暂时更改为std::string,看看是否仍然报告泄漏......(啊......我从另一条评论中看到你已经尝试过 - 好)。您是否检查过 delete[] 调用是否正在发生?您有时不会 erase-ing 一些没有 delete-ing 事先数据的键?
  • 在这个函数中,我用想要的字符填充我的 char*,然后执行:myMap[myCharPtr] = something。然后,在另一个函数中,我处理我的数据,然后我调用 freeMyMap(MyMap) 执行循环,然后执行 delete[] element->first。和我的第一篇文章一样。并且使用 std::string,没有内存泄漏。正如 Mike Seymour 所说,我正在尝试使用 unique-ptr。我会告诉你它是否有效。
  • 我刚刚看到您编辑了您的评论。我的代码的另一部分没有删除。
  • @Atouk 恐怕还有太多的事情无法帮助您获得更多帮助 - 您应该尝试获得一个 20-30 行的完整程序,该程序足以说明您正在做什么生成 valgrind 泄漏报告,然后将其附加到您的问题中,这样我们就有了具体的工作。
【解决方案2】:

您的地图有两个元素,您需要删除第一个元素:it-&gt;firstchar*it-&gt;secondfoo。试试下面的代码:

for(std::map<char*, foo>::iterator it = myMap.begin(); it!=myMap.end(); it++)
{
     delete[] it->first;
     myMap.erase(it);
}

希望有帮助!

【讨论】:

  • if 看起来他正在使用 c++11,所以他的循环很好,他不需要所有可怕的迭代器。调用擦除不是一个坏主意,但不应该是必要的,因为地图应该在销毁时自行清空。事实上,调用 myMap.clear();在循环之后可能会更快。
  • @Arunas:我同意你的看法!事实上,我正在考虑用其他方法来实现他所要求的而不使用 char*,尤其是在看到他对问题的编辑之后。
【解决方案3】:

已解决

谢谢大家,你们的大量 cmets 帮助解决了我的问题。我成功使用了 std::string。我知道,我告诉过你它太重了。但是我找到了 reserve(size_t n=0) 方法,它允许我们想要的地方。现在,没有泄漏了。

再次感谢您的回答!

来源: http://www.cplusplus.com/reference/string/string/reserve/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-21
    • 2013-01-05
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多