1

如何在将映射从一个函数传递到另一个函数时正确处理内存。

我有一个函数可以返回它构建的地图。值对象是一个类 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;  

单击此处查看我的实际代码。

更新: Foo 的成员变量未使用“新”运算符分配。因此,一旦超出范围,它们就会超出范围并具有垃圾值。

4

3 回答 3

1

确保您实际std::pair使用正确的值创建:

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

或利用std::make_pair

myMap.insert(std::make_pair(v, b));
于 2013-04-14T23:30:07.570 回答
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;
}

单击此处查看输出。

因此,问题必须在您的问题中未提及的内容中。为了能够进一步提供帮助,我们需要查看真实代码。

于 2013-04-15T00:14:47.500 回答
0

您在哪里评论过“在此处打印 FOO”,您甚至是如何编译它的?您无法Foo通过其中b任何一个地方的局部变量进行打印,因为它超出了范围。相反,您必须从地图中检索对象

我对您的代码进行了以下更改,一切正常:

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对象,你必须使用delete某个地方来清理它们,否则你的程序会内存泄漏。因此,人们通常不会将指针直接放入映射或列表中。相反,只需将Foo对象的副本放入(无指针),或者使用诸如 a 之类的包装器shared_ptr来为您管理删除。

于 2013-04-14T23:45:30.053 回答