2013-04-14 69 views
1

如何正确处理内存,同时将地图从一个函数传递到另一个函数。std ::映射值在返回后丢失

我有一个函数返回它构建的地图。值对象是一个foo类。 我在三个不同的位置打印foo,并且它们都给出不同的值。第一次,它给出了正确的值。第二和第三是垃圾。

我知道我必须在正确的地方制作Foo对象指针。

我想知道在哪里?

std::map<int,Foo*> function_that_returns_the_map(){ 

    std::map<int,Foo*> myMap; 

    { 

    int v = 0; 
    Foo *b = new Foo(); 

    // PRINTING FOO FIRST 

    std::cout<<""<<*b<<endl; 

    myMap.insert(std::pair<int,Foo*>(v,b)) 

    } 

    // PRINTING FOO AGAIN 

    for(map<int,Foo*>::iterator it = myMap.begin(); 
    it != myMap.end(); ++it) 
    {  
    std::cout << " " << *(it->second) << "\n"; 
    } 


    return myMap; 
    } 

std::map<int, Foo*> myMap; 
myMap = function_that_returns_the_map(); 

//PRINTING FOO AGAIN. 

std::map<int, Board*>::iterator it = myMap.begin(); 
for (it=myMap.begin(); it!=myMap.end(); ++it) 
    cout<<" "<<*(it->second)<<endl; 

Click here看到我的实际代码。

更新:Foo的成员变量没有使用'new'运算符分配。因此,他们超出了范围,并在垃圾价值超出范围之后出现。

+0

请张贴无需修改即可演示问题的代码。你是否意识到你实际上并没有将'b'放入地图? –

+0

也许你想'myMap.insert(std :: make_pair(v,b))'。不要忘记释放内存。 – 0x499602D2

+0

你是什么意思你“印刷富”?你无法打印课程。请显示打印的实际代码而不是注释。 – JBentley

回答

1

你的代码有很多小错误(我认为这只是拼写错误)。我固定的,并提供了Foo类,并将其编译和运行良好,在所有三个地方打印正确的值:

#include <iostream> 
#include <map> 

struct Foo 
{ 
    Foo() : someValue(5) {}; 
    int someValue; 
}; 

std::map<int,Foo*> function_that_returns_the_map() 
{ 
    std::map<int,Foo*> myMap; 
    { 
     int v = 0; 
     Foo *b = new Foo(); 
     std::cout << (*b).someValue << std::endl; // PRINTING FOO FIRST 
     myMap.insert(std::pair<int,Foo*>(v,b)); 
    } 

    // PRINTING FOO AGAIN 
    std::map<int, Foo*>::iterator it = myMap.begin(); 
    for(it; it != myMap.end(); ++it) 
    { 
     std::cout << it->second->someValue << "\n"; 
    } 
    return myMap; 
} 

int main() 
{ 
    std::map<int, Foo*> myMap; 
    myMap = function_that_returns_the_map(); 

    //PRINTING FOO AGAIN. 

    std::map<int, Foo*>::iterator it = myMap.begin(); 
    for (it; it!=myMap.end(); ++it) 
    std::cout << it->second->someValue << std::endl; 
    return 0; 
} 

Click here查看输出。

因此,这个问题必须在你的问题中没有提到的问题。为了能够进一步提供帮助,我们需要查看真实的代码。

+0

JBentley,谢谢。你的代码显示指针没有任何问题。我试图找出什么是错的。一旦我这样做,我会标记你的答案是正确的。同时,我把所有的功能都完全包含在这里(http://ideone.com/7kE5rL)。如果你能看看它,我将不胜感激。 – srrvnn

+0

发现错误,我在填写Foo的值时未使用新的操作符。你在Orion的解释评论回答你说的话:“Foo对象本身仍然在堆中,因为你用新创建了它”让我意识到我没有使用new创建我在Foo中存储的数组。谢谢! – srrvnn

1

确保您实际创建std::pair了正确的价值观:

myMap.insert(std::pair<int,Foo*>(v, b)); 
//        ^^^^ 

或利用std::make_pair:“这里的印刷FOO”

myMap.insert(std::make_pair(v, b)); 
+0

道歉。我在代码中犯了一个错误。实际上,我使用v和b值。我在重写代码时错过了它们。 – srrvnn

+0

我的问题是:我应该在哪里制作foo,以便它的值在调用函数的地图上可用,尽管地图存储了指针? – srrvnn

0

你到哪儿去评论你怎么连编译它?您无法在任何地方通过b局部变量打印Foo,因为它超出了范围。您而必须检索对象缩小地图

我做了以下修改你的代码,而这一切工作正常:

class Foo 
{ 
public: 
    const int Value; 
    Foo(int value) : Value(value) // add some kind of identifier to Foo so we can check it's not garbage 
    { } 
}; 

std::map<int,Foo*> function_that_returns_the_map() 
{ 
    std::map<int,Foo*> myMap; 

    { // introducing a new scope 

     int v = 0; 
     Foo *b = new Foo(98765); 

     // PRINTING FOO HERE. 
     std::cout << b->Value << std::endl; 

     myMap.insert(std::pair<int,Foo*>(v,b)); 
    } // v, b go out of scope, are no longer accessible 

    // PRINTING FOO HERE. 
    std::cout << myMap[0]->Value << std::endl; // we can't use v, b anymore, so go fish in the map to find the Foo 

    return myMap; 
} 

void main() 
{ 
    std::map<int, Foo*> myMap; 
    myMap = function_that_returns_the_map(); 

    //PRINTING FOO HERE. 
    std::cout << myMap[0]->Value << std::endl; // we can't use v, b anymore, so go fish in the map to find the Foo 
} 

的关键是作用域。 C++中的大括号意味着范围。在该范围内声明的任何局部变量不能从外部使用。希望这将有助于解释它。如果没有,请评论任何没有意义的事情。

PS:记住,因为你已经使用new创建您Foo对象,你MUST使用delete地方清除它们,否则你的程序将内存泄漏。因此,人们通常不会将指针直接放入地图或列表中。相反,只需将Foo对象的副本放在(无指针)中,或者使用包装器(如shared_ptr)来管理您的删除。

+0

我不确定这个答案是否适用,因为他用更多的代码编辑了这个问题。 – JBentley

+0

感谢您的回答。我只是修改了代码以显示我如何打印。我正在从地图中检索值。大括号可以显示范围。 地图指向的值是一个指针。由于该分配超出了函数内部花括号的范围,这是否意味着值98765不会退出? – srrvnn

+0

@srrvnn你添加的花括号不会显示范围,它们会创建一个新的范围。 – JBentley