2013-04-14 66 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