在循环中迭代后共享指针断言失败

时间:2016-02-08 20:42:51

标签: c++ pointers boost iterator shared-ptr

我是来自boost的shared_ptr的新手,我正在考虑迭代我的设置以获得最佳对象。 编辑:添加了有关first_world

的信息
std::set<World::CPtr> first_world = ... // long call, but it gets a set of constant shared pointers to the class World, where various methods exist

   typedef boost::shared_ptr<World const> CPtr;
   World::CPtr best = *(first_world.begin());
   for (World::CPtr lo : first_world) {
     if (best->getValue() >= lo->getValue() ){
       best = lo;
     }
   }

后来我想使用那个共享指针,我的程序崩溃与Assertion`px!= 0'的通信失败。我遵循here的规则,我的意思是我在循环中使用了共享指针作为迭代器,但后来我将它分配给另一个指针。这是不好的做法,还有更好的做法吗?

cout << "name is: " << best->getDefinition() << endl;

1 个答案:

答案 0 :(得分:0)

在那里粘贴的东西没有什么明显的错误,所以在创建该集合的长期通话中可能会出现错误。

例如,如果在向集合中添加元素时涉及原始指针,则很容易搞砸了。考虑这种情况,一个具体的例子,说明您的最佳实践链接中提到的一个常见错误:

std::set<World::CPtr> first_world;

World* pWorld = new World();

// Bad:
first_world.insert(World::CPtr(pWorld));
first_world.insert(World::CPtr(pWorld));

// Oops!! You now have two independently refcounted entries in first_world!

// emplace is just as deadly, but more subtle.
// Now you'll have three shared pointers in your set:
first_world.emplace(pWorld);

如果您查看first_world中的条目并查看重复项,那么您就会知道自己遇到了麻烦。为了避免这样的错误,请确保只从其他shared_ptrs(或boost::make_shared)构造shared_ptrs。

这样的提示#1:避免从原始指针构建shared_ptrs 。 (这包括this指针,如果世界将自己添加到您的集合中...如果您正在这样做,最好开始使用Google搜索enable_shared_from_this)。

现在让我们遵循该指南以获得预期的行为:

std::set<World::CPtr> first_world;

World::CPtr spWorld1 = boost::make_shared<World>();
World::CPtr spWorld2{spWorld1};

first_world.insert(spWorld1);
first_world.insert(spWorld2);
// Just one element in first_world now, as expected.

最后,一些(有点无关)的建议:

  • std::set因为您已经声明它在比较条目时只查看堆上的World对象的地址。因此,如果堆上有两个逻辑上相同的不同世界,那么它们在集合中都有不同的条目。这是你的意图吗?如果你想避免逻辑重复,你需要插入你自己的自定义比较函数(std :: set的第二个模板参数)来对世界进行深度比较。
  • 检查以确保first_world在找到最大值之前不是空的,否则会发生不好的事情。
  • 标准算法是你的朋友!考虑使用std::max_element算法而不是原始循环。 (这使得其他人更容易通过快速浏览来推断您正在做的事情。)