所以我完全编辑了我的问题。
我有map
名为mTextMap
,其中包含:
typedef std::map<const std::string, Text*> TextMap;
TextMap mTextMap;
我有以下方法:
void Foo::setUpGame()
{
Text text(1,2,3,4); //create a Text object
mTextMap["MainText"] = &text; //save it in the map!
}
Text& Foo::getText(const std::string name)
{
auto i= mTextMap.find(name);
return *(i->second); //Gets a reference to the Text that is inside the map
}
现在,如果我这样使用:
Foo foo;
foo.setUpGame();
Text& myText = foo.getText("MainText"); // Why is this corrupted?
对象myText
已完全损坏!!
为什么会这样?
答案 0 :(得分:2)
一般问题似乎是,你认为这一行:
mTextMap["MainText"] = &text;
将文本对象存储在地图中。它没事了!它存储一个指向地图中对象的指针,文本对象本身 - 如你所说 - 在函数结束时自动被破坏。所以现在你的指针指向一个不存在的对象,这会导致观察到的错误。
您的问题有多种解决方案,具体取决于您尝试实现的具体目标以及您将如何处理您的课程。
一种可能性是使用Text对象的地图(而不是指针):
typedef std::map<const std::string, Text> TextMap;
void Foo::setUpGame()
{
Text text(1, 2, 3, 4); //create a Text object
mTextMap["MainText"] = text; //copy it into the map!
}
或
void Foo::setUpGame()
{
mTextMap.emplace("MainText", Text(1, 2, 3, 4)); //Doesn't require Text to be default constructable
}
另一种可能性是在堆上创建文本对象并使用智能指针(例如unique_ptr)
typedef std::map<const std::string, std::unique_ptr<Text>> TextMap;
void Foo::setUpGame()
{
mTextMap["MainText"] = std::make_unique<Text>(1,2,3,4); //create object on the heap an store a pointer to it in the map
}
一旦地图被破坏,std::unique_ptr
将自动销毁文本对象。
如果由于某种原因你真的需要有一个原始指针的地图,你可以使用&#34; new&#34;正如David所解释的那样,但是当你不再使用它们时别忘了删除它们--c ++没有垃圾收集器(比如java)可以自动处理它。 / p>
答案 1 :(得分:1)
当您为对象动态分配内存时,只要您没有从内存中显式删除它,它就会存在,在您退出创建它的方法后它不会被删除,因此您可以在其中放置指针一张地图,它将永远存在(只需确保从地图中删除对象时删除内存)。
您可以使用以下简单代码对其进行测试,其中我在函数中声明一个新的Int,返回指向内存的指针并将其打印在接收映射的另一个函数中(其中包含指针)。它打印正确,这意味着即使超出范围也不会释放内存。
#include <iostream>
#include <map>
std::map<std::string, int*> myMap(){
int* test = new int(1);
std::map<std::string, int*> ObjMap;
ObjMap["object"] = test;
return ObjMap;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::map<std::string, int*> mmap = myMap();
std::cout << *mmap["object"] << std::endl;
return 0;
}
所以要回答你的问题,请动态创建你的对象:
Obj* obj = new obj(1,2,3,4);
超出范围时不会删除。尽管如此,除非你使用智能指针,否则你需要自己删除内存,如下所示:delete obj;
(当你从地图中删除它时,释放内存,因为它不会自动释放)。
PS:您应该阅读堆栈和堆的工作原理以及动态和静态分配的工作原理(使用堆栈或堆)。 See this c++ dynamic memory allocation tutorial to have more informations.
像 MikeMB 所说,使用智能指针更容易,因为您确定删除了内存,并且您也确定永远不会访问已删除的内存。有关智能指针信息,请参阅此Stack Overflow主题:What is a smart pointer and when should I use one?
答案 2 :(得分:1)
&#34; text&#34; setUpGame完成后,对象将超出范围。此时,堆内存被释放,以便被堆的任何新用途覆盖。它本质上是项的临时暂存器,它只存在于函数的范围内(或者在函数内的显式范围操作符中)。
David G的建议是合理的:阅读更多关于堆栈和堆内存之间的区别,并考虑使用智能指针的建议。但是,如果您想要对您当前的问题进行廉价,肮脏的修复,可以试试这个:
void Foo::setUpGame()
{
static Text text(1,2,3,4); // Note use of "static" keyword
mTextMap["MainText"] = &text; //save it in the map!
}
虽然我并不主张使用静态作为解决更基本的架构内存问题的捷径,但如果您急于让事情发挥作用,您可以将其作为一种短期措施。将对象标记为静态可确保其生命周期超出函数的范围。但我不建议将其作为这类问题的长期解决方案。