Как справиться с этой проблемой C ++ Multimap? - PullRequest
0 голосов
/ 09 февраля 2020

Я новичок в C ++, работающий над простой программой, и я столкнулся с проблемой, которая оставила меня в тупике ... По сути, я создал мультикарту, которая принимает часть строкового имени человека и указатель на объект person.

Итак, моей первой функцией для работы была функция «Add ()». Я в основном создаю нового человека с именем и возрастом, а затем устанавливаю указатель на этот объект. Затем я вставляю имя и объект в мультикарту в виде пары.

Проблема возникает, когда я запускаю функцию find () ... Мой вывод дает мне только правильное имя, но для возраста я получаю то, что похоже на усеченный адрес памяти или случайное число? Поскольку я новичок, я почти уверен, что делаю что-то очень простое, но очень глупое. Я не думаю, что вам нужно будет запускать код, так как это так просто. Вся помощь приветствуется. Спасибо!

Мой исполняемый файл:

#include "Person.h"
#include <map>
using namespace std;

multimap<string, Person*> personMap;
multimap<string, Person*>::iterator counter;


void add()
{
  string name;
  int age;
  cout << "Please enter the name of the person: ",  cin >> name;
  cout << "Please enter the age of the person: ", cin >> age;
  Person generatedPerson(name, age);

  // Avoid dynamic class pointers for memory optimization.
  // Avoided: Person* pointer = new Person(name, age).
  Person *pointer = &generatedPerson;
  personMap.insert({name, pointer});

}

void find()
{
  string personToBeFound;
  cout << "Who do you wish to find, friend: ", cin >> personToBeFound;


  for (counter = personMap.begin(); counter != personMap.end(); counter++)
  {
    if (counter->first == personToBeFound)
    {
      cout << "\nName: " << counter->first << " Age: " << counter->second->getAge() << endl;
    }
    else if (counter->first != personToBeFound)
    {
      cout << "Error 404, person does not exist..." << endl;
    }
  }
}

// Experimental....
int main(int argc, char* argv[])
{
  int menuChoice = -1;

  while (menuChoice != 0)
  {
    cout << "\nPlease enter: "
            "\n1 - to add a person "
            "\n2 - to find a person"
            "\n0 - to quit\n" << endl;
    cin >> menuChoice;
    switch(menuChoice)
    {
      case 1: add();
        break;
      case 2: find();
        break;
      case 0: menuChoice = 0;
    }
  }
}

ФАЙЛ ХАЙДЕРА:

#ifndef PERSON_H
#define PERSON_H

#include <string>
#include <vector>
#include <iostream>

class Person {
 public:
  // Constructors

  /**
   * Create a Person with the given name and age.
   *
   * @param name name of the person
   * @param age age of the person - defaults to 0
   */
  Person(const std::string& name, unsigned short age = 0);


  // No explicit destructor necessary


  // Mutators

  /**
   * Set the name attribute
   *
   * @param name name of the person
   */
  void setName(const std::string& name);

  /**
   * Set the age attribute
   *
   * @param age age of the person
   */
  void setAge(unsigned short age);

  /**
   * Increment the age attribute
   */
  void growOlder();

  /**
   * Add a person to our list of children
   *
   * @param child Person to add as a child
   */
  void addChild(const Person& child);


  // Accessors

  /**
   * @return the Person's name
   */
  const std::string& getName() const;

  /**
   * @return the Person's age
   */
  unsigned short getAge() const;

  /**
   * @return a list of this Person's children
   */
  const std::vector<const Person *>& getChildren() const;

  /**
   * Define the ostream's << operator as a friend of this class
   * to allow this object to be printed to an output stream
   *
   * @param output the stream to print to
   * @param p the Person to print
   *
   * @return the output stream printed to
   */
  friend std::ostream& operator<< (std::ostream& output, const Person& p);


 private:

  // 0-arg Constructor
  Person();

  // Private attributes
  std::string _name;
  unsigned short _age;
  std::vector<const Person *> _children;

}; // Person

#endif

ОПРЕДЕЛЕНИЯ МЕТОДА:

#include "Person.h"

Person::Person(const std::string& name, unsigned short age) :
    _name(name) , _age(age) {
}


void Person::setName(const std::string& name) {
  _name = name;
}


void Person::setAge(unsigned short age) {
  _age = age;
}


void Person::growOlder() {
  _age++;
}


void Person::addChild(const Person& child) {
  _children.push_back(&child);
}


const std::string& Person::getName() const {
  return _name;
}


unsigned short Person::getAge() const {
  return _age;
}


const std::vector<const Person *>& Person::getChildren() const {
  return _children;
}


std::ostream& operator<< (std::ostream& output, const Person& aPerson) {
  // Print our attributes to the output stream
  return output << "Name: '" << aPerson._name << "', Age: " << aPerson._age;
}

1 Ответ

0 голосов
/ 09 февраля 2020

Привет, комментарий @ 1201ProgramAlarm абсолютно прав, однако, я подумал сам, как бы я go о "спасении" программы (а) с минимальными усилиями, (б), чтобы получить правильную версию и (c) очень сильно с точки зрения исходной версии.

Итак, вот новая main.cc версия (Person.h, Person.cc менять не нужно):

#include "Person.h"
#include <map>

using namespace std;

multimap <string, Person *> personMap;
multimap <string, Person *>::iterator counter;


void add()
{
    string name;
    int    age;

    cout << "Please enter the name of the person: ", cin >> name;
    cout << "Please enter the age  of the person: ", cin >> age;

    personMap.insert({ name, new Person(name, age) });
}


void find()
{
    string personToBeFound;

    cout << "Who do you wish to find, friend: ", cin >> personToBeFound;

    for (counter = personMap.begin(); counter != personMap.end(); counter++)
    {
        if (counter->first == personToBeFound)
        {
            cout << "\nName: " << counter->first
                 <<   " Age: " << counter->second->getAge() << endl;
        }
        else
        {
            cout << "Error 404, person does not exist..." << endl;
        }
    }
}


int main(int argc, char* argv[])
{
    int    menuChoice = -1;
    while (menuChoice != 0)
    {
        cout << "\nPlease enter: "
            "\n1 - to add a person "
            "\n2 - to find a person"
            "\n0 - to quit\n" << endl;

        cin >> menuChoice;
        switch(menuChoice)
        {
        case 1:
            add();
            break;

        case 2:
            find();
            break;

        case 0:
            menuChoice = 0;
            break;
        }
    }

    // -- How to go about clearing the heap? --

    for (counter = personMap.begin(); counter != personMap.end(); counter++)
    {
        if (counter->second) {
            delete   counter->second;
            counter->second = nullptr;
        }
    }
}

Я скомпилировал, используя g++ -o main Person.cc main.cc. С уважением, М.

Обновление после этого вопроса :

Почему бы мне просто не удалить ключи вместо значений multimap <string, Person *> записей?

Ответ :

Я просто хотел показать, что можно сделать для предотвращения осиротевших Person объектов в куче, когда multimap вышел (локальной) области и, таким образом, будет автоматически уничтожен системой C++. Более конкретно:

(a) Как и в C, то, что malloc -ed, должно быть снова free -ed позже, эквивалентно истинно в C++: что new -ed должен быть delete -ed позже. Это лучшая практика для предотвращения утечек памяти в долгосрочной перспективе.

(b) Теперь вернемся к нашему multimap <string, Person *>. Здесь ключи string с, а значения указатели на Person объектов. Эти Person указатели - единственный оставшийся способ удержать соответствующие Person объекты , выделенные в куче при вызовах функции add().

(c) В нашем случае вся программа будет остановлена ​​в любом случае после автоматического уничтожения multimap, поэтому delete -ing Person объектов с использованием этого дополнительного for - l oop здесь не так важен, потому что Person объекты, остающиеся в куче, собираются сборщиком мусора операционной системой после завершения соответствующего процесса, так или иначе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...