【问题标题】:Deleting an edge from edges_ that is declared as std::set<std::shared_ptr<Edge>> edges_;从 edge_ 中删除一条声明为 std::set<std::shared_ptr<Edge>> edges_ 的边;
【发布时间】:2016-09-17 16:29:50
【问题描述】:

我是 std::shared_ptr 和 std::set 的新手。对于以下代码,我想知道如何从edges_中删除边缘。

edges_ 被声明为std::set&lt;std::shared_ptr&lt;Edge&gt;&gt; edges_;,我想删除存储在std::set 中的共享指针所引用的边。我的部分代码在这里,但似乎有问题。

auto findEdge = findLinkingNode1->second->edges_.find(edge);
findLinkingNode1->second->edges_.erase(findEdge);

错误:

test8c(3034,0x7fff78df2000) malloc: *** error for object 0x7f8553403350: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

考虑到共享指针存储在std::set中,如何从edges_中删除边缘,这是通过共享指针管理的?

【问题讨论】:

  • 你应该检查 find 的返回,以防它不成功。除此之外,存储在您试图销毁的共享指针中的指针是否分配在堆上?它是如何分配的?
  • Edges 是多态的还是包含大量数据?如果不是,那为什么要使用共享指针呢?价值语义可以是一个巨大的胜利。
  • edges_中存储的边是共享指针。它通过 std::make_shared 从边转换为共享指针。 “new”不是用来制作指针指向的对象,所以我认为它没有分配在堆上。至于边,是的,它们是多态的,因为 Graph 的通用模板类与不同类型的函数模板一起使用,节点和边结构是该图类的一部分。
  • findOrig->second->edges_.insert(std::make_shared(Edge (findOrig->second, findDest->second, val)));
  • 关于多态:Edge 是否包含虚成员函数?

标签: c++ graph iteration shared-ptr stdset


【解决方案1】:

这只是猜测,但鉴于您提供的代码......

auto findEdge = findLinkingNode1->second->edges_.find(edge);
findLinkingNode1->second->edges_.erase(findEdge);

...我想说你的问题是你正在擦除 edges_.end() which is not allowed (可能是未定义的行为):

迭代器pos 必须有效且可取消引用。因此,end() 迭代器(有效,但不可取消引用)不能用作 pos 的值。

如果在集合中找不到给定的edge,变量findEdge 将等于edges_.end()。要查找元素,std::set 使用 Compare 对象,其类型通过第二个模板参数定义...

std::set<std::shared_ptr<Edge>> edges_;

...您没有指定,因此它默认为std::less&lt;std::shared_ptr&lt;Edge&gt;&gt;,而后者又调用the operator&lt; of the shared pointer,它...

请注意,shared_ptr 的比较运算符只是比较指针值;不比较指向的实际对象。

... 不比较对象,只比较指针。因此,如果用于插入和搜索的指针不是指向完全相同的(如在相同的,不仅仅是“相等”)对象中,你就麻烦了。


以上是猜测,但鉴于您的评论......

findOrig->second->edges_.insert(std::make_shared<Edge>(Edge (findOrig->second, findDest->second, val) ));

... 事实证明,因为(几乎)没有办法获取make_shared 返回的指针。

解决方案:为您的集合实现一个比较类,用于比较实际的 Edge 对象。 (摆脱指针并不是那么简单,因为你说Edge 是多态的)

士气:始终测试可能的错误情况。

【讨论】:

  • 那么你所说的比较类,是为了能够从edges_中删除边缘吗?为什么make_shared返回的指针根本无法返回?所以我根本无法删除边缘?
  • find 函数的edge 参数需要与插入调用中make_shared 返回的指针相同(或其副本)。你如何获得edge,即分配给它的内容?
  • 你的意思是边缘类里面有什么?如上所述。
猜你喜欢
  • 2014-09-08
  • 2018-07-18
  • 2017-09-15
  • 2016-01-03
  • 2020-08-06
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
相关资源
最近更新 更多