【问题标题】:How to use STL map?如何使用 STL 映射?
【发布时间】:2013-01-09 14:26:52
【问题描述】:

我有一个私人领域

std::map<std::string, std::multiset<GraphObject*>>* the_Map;

如何为其分配内存并插入 GraphObject? 我必须使用 new 运算符吗?

the_Map = new map<string,multiset<GraphObject*>>;

我怎样才能插入一个新的 GraphObject? 它是数据结构的一部分,我真的需要一个指向地图的指针。

【问题讨论】:

  • std::map&lt;std::string, std::multiset&lt;GraphObject*&gt;&gt; the_Map;(不是指针,不是new,什么都没有)可以正常工作。
  • 首先,您真的需要指向地图的指针吗?其次,您是否可以访问文档?
  • 为什么一开始就将字段声明为指针?
  • 我无法更改字段。它是数据结构的一部分,我需要访问整个班级的地图。
  • 让我想起了 Bjarne 的评论:“如果那是 C++,我也讨厌它。”使用指针而不是(自动存储类)映射对象不会使整个类更容易访问它。

标签: c++ memory-management maps


【解决方案1】:

如何为其分配内存并插入 GraphObject?

它根本不想成为指针;只需让地图本身成为该类的成员,内存分配就会自动发生。

正确插入一个对象是相当繁琐的,因为你也在那里存储指针。如果它不需要是一个指针,那么存储对象会让你的生活更轻松。如果它确实必须是一个指针(例如,因为GraphObject 是一个多态基类),我建议存储智能指针:std::unique_ptr,或std::tr1::shared_ptr 或boost::shared_ptr,如果你被困在过去。

如果你真的,真的因为某些疯狂的原因需要使用原始指针,那么最接近异常安全插入的可能是:

GraphObject * object = new Whatever(...);
try {
    the_Map[key].insert(object);
} catch(...) {
    delete object;
    throw;
}

或者如果您不关心插入失败时内存泄漏的可能性:

the_Map[key].insert(new Whatever(...));

也不要忘记删除每个对象时删除它;这不会自动发生。

我真的需要一个指向地图的指针。

不,你没有。但是,如果您真的相信自己做到了,并且想忽略每个人的建议,那么您将需要一张实际的地图来指向。我建议您将此映射设为该类的成员,以便自动管理其生命周期。

如果你真的想让维护代码的人生活困难,那么我想你可以用new 分配一个。在这种情况下,请记住在完成后将其删除;可能在类析构函数中。如果您这样做,请记住 Rule of Three 并实现或删除复制构造函数和复制赋值运算符,因为默认实现会做错事。

【讨论】:

  • 这个答案比我的好很多。
【解决方案2】:

为什么要存储GraphObject * 的::std:multiset 有点晦涩,但让我们继续吧。

这是一个在文档中确实可以轻松回答的答案,但对于 StackOverflow 来说毫无疑问太愚蠢了,所以...

 the_Map = new map<string,multiset<GraphObject*>>;

这确实是您为地图分配内存的方式。对周围的事物有简单的指针通常不是一个好主意,但你坚持,这就是你的做法。这意味着您也必须在某个时候记住delete。而且你必须确保持有指针的类的复制结构做正确的事情(并且说正确的事情会相当复杂)。

你现在有一个有趣的问题。您在每个映射条目中存储一个multiset。幸运的是,当访问以前未知的键时,该多重集将自动创建并初始化为空。 OTOH,您使用裸指针意味着您有异常安全问题。如果在此过程中的任何地方抛出异常,则可能会泄漏内存。所以你必须捕获任何异常并清理你的对象:

 GraphObject *tmp = new GraphObject;
 try {
     (*the_Map)[key].insert(tmp);
 } catch (...) {
     delete tmp;
     throw;
 }

您的问题是如此基本的事实使我质疑您关于需要使用指针的断言。我真的想知道你是否宁愿拥有multimap 而不是来自string -> multiset 的map。但是,您坚持数据结构的一般形式。以上就是你的使用方法了。

我还要说,这种数据结构大量使用裸指针是一个非常糟糕的主意。您必须编写一个非常复杂的函数才能正确解构或复制整个混乱。

编辑:sigh 凌晨 4 点在我自己永远不会创建的数据结构上进行编码导致我编写了一些非常愚蠢的代码。现在的版本好多了。虽然this answer 确实比我好很多。

【讨论】:

  • 虽然我同意您的 cmets 关于指针的使用,但在这种情况下,他应该能够简单地执行 (*the_Map)[key].insert(new GraphObject) 而无需查找。如果存在,[] 将返回对它的引用。如果它不存在,它会创建一个新的空多重集。
  • @DaveS:拍打额头你说得对!对我来说 Python 编程太多了。
猜你喜欢
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 2011-04-08
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多