我正在编写一个小型游戏引擎作为夏季项目,并且正在与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中更好,我会在那里发布。
答案 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::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>
而不是原始指针吗?管理对象生命周期会更安全,更简单。
答案 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。
您需要在某处添加一些代码以在检查之前检查空指针。