Как правильно передать std::map между двумя объектами?

У меня есть объект фабричного метода, который создает карту следующим образом:

// std namespace is imported

Foo* createFoo() {
   map<int,int>* fooMap = new map<int,int>();
   for (int i=0;i < 4;i++) {
      fooMap->insert(make_pair(i+1, i+2));
   }
   return new Foo(fooMap);
}

Класс foo выглядит следующим образом:

class Foo { 
    private: 
        map<int,int>* m_fooMap; 
    public: 
        Foo(map<int,int>* fooMap) : m_fooMap(fooMap) { }; 
        void doIt() {
            cout << m_fooMap->at(1) << endl;
        }
}

Кажется, это вызывает исключение, если я вызываю функцию doIt. Когда я отлаживал, я заметил, что объект карты, похоже, не создается и не заполняется. Как правильно создать карту в куче?

PS: я не хочу создавать карту и передавать по значению, я бы предпочел сделать это с помощью указателя в качестве учебного упражнения. Кроме того, если я создаю карту в стеке, она заполняется, но, конечно, я не могу передать ее объектам Foo, поскольку она выходит за рамки.


person dev_nut    schedule 30.05.2013    source источник
comment
Почему все динамическое распределение? Просто выделяйте автоматические объекты и возвращайте их по значению.   -  person juanchopanza    schedule 30.05.2013
comment
Я хотел бы научиться делать это правильно. Я знаю, что передача по значению будет работать, но я хотел бы понять, почему это не работает.   -  person dev_nut    schedule 30.05.2013
comment
Чтобы сделать это правильно, нужно избежать всех этих динамических распределений. Вы учитесь не делать это правильно.   -  person juanchopanza    schedule 30.05.2013
comment
Пожалуйста, представьте полный пример кода, демонстрирующий проблему. Опишите свой результат и то, как он отличается от ваших ожиданий.   -  person Benjamin Lindley    schedule 30.05.2013
comment
Вам нужно показать код, используя Foo, все, что вы здесь разместили, в порядке (хотя, как и выше, вам не нужно выделять Foo в куче, в любом случае весь объект имеет тот же размер, что и указатель)   -  person Salgar    schedule 30.05.2013
comment
@Salgar, хотя есть утечка памяти, так что не все в порядке.   -  person juanchopanza    schedule 30.05.2013
comment
Я снова отредактировал вопрос... Думаю, я хочу научиться писать эффективный C++, поэтому могу ли я спросить, не является ли передача по значению ударом по производительности?   -  person dev_nut    schedule 30.05.2013
comment
@dev_nut: Не обязательно.   -  person Jerry Coffin    schedule 30.05.2013


Ответы (1)


Я бы предпочел подход без явного выделения динамической памяти:

class Foo { 
    private: 
        std::map<int,int> m_fooMap; 
    public: 
        Foo(const std::map<int,int>& fooMap) : m_fooMap(fooMap) {}; 
        Foo(std::map<int,int>&& fooMap) : m_fooMap(std::move(fooMap)) {}; 
        void doIt() {
            cout << m_fooMap.at(1) << endl;
        }
};

Foo createFoo() 
{
   std::map<int,int> fooMap;
   for (int i=0;i < 4;i++) {
      fooMap.insert(make_pair(i+1, i+2));
   }
   return Foo(fooMap);
}
person juanchopanza    schedule 30.05.2013
comment
За исключением того, что это меняет подпись, и он сказал, что хочет сделать это динамически с помощью указателей. - person UpAndAdam; 30.05.2013
comment
@UpAndAdam Верно, но я думаю, что требования ОП ошибочны. - person juanchopanza; 31.05.2013
comment
Я знаю, как это сделать сам, я просто хочу сказать, что вы обходите всю проблему его вопроса, изменяя это ограничение. В любом случае классические фабричные методы Gang-of-Four всегда должны будут возвращать указатель. Важная часть полиморфной цели фабричного метода состоит в том, чтобы отделить знания и способы создания сложных объектов от вызывающих/использующих классов. Если он должен знать, какой конкретный тип использовать с самого начала, вы не можете этого сделать. stackoverflow.com/questions/1031301/ - person UpAndAdam; 31.05.2013