C ++地图可以包含指向我任意类的指针吗?

时间:2012-07-09 20:51:44

标签: c++ pointers stl map

我正在编写一个小型游戏引擎作为夏季项目,并且正在与STL地图挣扎。

我已声明一个类RenderList来保存对象。 RenderList将传递给Renderer类来完成工作。

RenderListmap<std::string,Entity*> objects;

这一切都有效,直到我试图从地图中获得Entity*并得到:

断言失败,在vc / include / xtree中 表达式:map / set iterator not dereferencable。

这是检索指针的代码。

Entity* RenderList::getByName(std::string str){
    return objects.find(str)->second;
}

我需要它来保存指针而不是实际的对象,因为我需要Entity的不同子类。

我是STL的新手,我不应该在地图中存储指针吗?

当然我应该被允许这样做,或者更好的想法来存储对象?

最后,我只是做错了!?

希望这个问题不重复,我事先做了快速搜索。如果这在GameDev Stack中更好,我会在那里发布。

5 个答案:

答案 0 :(得分:8)

如果找不到密钥,那么map::find(key)将返回一个“past-the-end”迭代器,即map::end()返回的值,并且迭代器不指向任何元素,所以可以'被解除引用。在解除引用之前,您不会检查find返回的内容。

你确定他们的钥匙在地图上吗?

如果找不到密钥,您可能希望执行返回NULL的操作,您可以通过将返回的迭代器与end进行比较来检查,例如。

Entity* RenderList::getByName(std::string str){
  map_type::iterator it = objects.find(str);
  if (it == objects.end())
    return NULL;
  return it->second;
}

RenderList定义typedef:

typedef map<std::string,Entity*> map_type;

(NB我总是让我的类为我用作实现细节的容器定义typedef,因为写map_type::iteratormap<std::string,Entity*>::iterator更容易,因为如果我改变容器到其他东西我没有必要改变使用它的所有代码,例如map<std::string,shared_ptr<Entity>>::iterator我可以把它保留为map_type::iterator,它仍然可以完美地工作。)

关于一般设计,您可以存储boost::shared_ptr<Entity>std::tr1::shared_ptr<Entity>而不是原始指针吗?管理对象生命周期会更安全,更简单。

答案 1 :(得分:3)

这可能意味着您要查找的名称在地图中不存在。如果密钥不存在,find方法将返回映射的结束迭代器,这确实不是可解除引用的。

如果“未找到”的情况自然会发生,那么你可以这样做

Entity* RenderList::getByName(std::string str){
    map<std::string,Entity*>::iterator it = objects.find(str);
    return it != objects.end() ? it->second : NULL;
}

因此将处理这种情况的责任传递给来电者。

如果不应该发生“未找到”的情况,要么抛出异常,要么至少做

assert(it != objects.end());

答案 2 :(得分:1)

这有一个问题是你需要处理没有匹配str的条目的情况。不知道具体的错误是什么,但是我很遗憾地(很遗憾地)在地图中完成了相同的操作来检索指针..

答案 3 :(得分:1)

如果地图不包含您传递给find方法的密钥,则会返回objects.end()。取消引用这是一个运行时错误,可能会导致您看到的错误。请尝试改为:

map<std::string,Entity*>::iterator findIt;
findIt = objects.find(str);

if ( findIt != objects.end() )
{
    return findIt->second;
}
else
{
   // Handle error here
}

答案 4 :(得分:1)

正如其他人所指出的,地图中不存在您正在查找的名称。每个人都很快建议您检查.find()的返回值。相反,我建议您不要致电.find()。以下是我将如何解决您的问题:

Entity* RenderList::getByName(std::string str){
  return objects[str];
}

在上面的代码中,查找不存在的映射条目将创建一个带有NULL指针值的条目,并返回NULL。

您需要在某处添加一些代码以在检查之前检查空指针。