0

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

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

RenderList一个map<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 中会更好,我会在那里发布。

4

5 回答 5

8

如果未找到该键,则map::find(key)返回一个“过去的”迭代器,即返回的值map::end(),并且该迭代器不指向任何元素,因此无法取消引用。find在取消引用之前,您不会检查返回的内容。

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

如果找不到键,您可能想要执行类似 return NULL 之类的操作,您可以通过将返回的迭代器与endeg进行比较来检查它

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;

(注意,我总是让我的类为我用作实现细节的容器定义 typedef,因为它比写起来容易map_type::iterator得多map<std::string,Entity*>::iterator,因为如果我将容器更改为其他东西,我不必将使用它的所有代码更改为例如map<std::string,shared_ptr<Entity>>::iterator我可以保持原样map_type::iterator,它仍然可以正常工作。)

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

于 2012-07-09T20:55:00.843 回答
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());
于 2012-07-09T20:54:53.907 回答
1

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

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

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

您需要在某处添加一些代码来检查空指针,然后再尊重它。

于 2012-07-09T20:57:45.903 回答
1

这样做的一件事是您需要处理没有匹配的条目的情况str。不确定具体的错误是什么,因为我(遗憾的是)对地图进行了同样的操作以检索指针..

于 2012-07-09T20:55:24.387 回答
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
}
于 2012-07-09T20:56:30.813 回答