En mi clase, tengo un mapa desordenado de vectores, como este:

std::unordered_map<State, std::vector<std::shared_ptr<const City>>> citiesByState;

Mi clase también tiene estos dos métodos:

  void addCity(State state, const std::shared_ptr<const City>& city);
  void removeCity(State state, const std::shared_ptr<const City>& city);

Añado una ciudad, como esta:

void Manager::addCity(State state, const std::shared_ptr<const City>& city) {
  auto location = citiesByState.find(state); // Find the state in the map
  if (location == citiesByState.end()) { // If the state isn't in the map
    std::vector<std::shared_ptr<const City>> cities; // Create a vector
    cities.push_back(city); // Add the city
    citiesByState[state] = cities; // Add the state and city vector to my map
  } else {
    auto vector = location->second; // Get the city vector. If the city isn't there already, add it.
    if (std::find(vector.begin(), vector.end(), city) == vector.end()) {
      vector.push_back(city);
    }
  }
}

Ahora aquí está mi código para eliminar una ciudad:

void Manager::removeCity(State state, const std::shared_ptr<const City>& city) {
  auto location = citiesByState.find(state);
  if (location != citiesByState.end()) {
    auto vector = location->second;
    if (vector.size() > 0) {
      std::cout << "Vector isn't empty." << std::endl;
    }
    vector.clear(); // Just empty it out for now.
  }
}

Entonces lo ejecuto así:

  City city = ... // get city
  manager->addCity(State::NewYork, city);
  manager->removeCity(State::NewYork, city);

Puedo llamar a manager->removeCity(State::NewYork, city) repetidamente, y cada vez veo que el vector no está vacío. Parece que no puedo eliminar del Vector.

¿Qué estoy haciendo mal?

0
Beebunny 14 mar. 2021 a las 12:17

1 respuesta

La mejor respuesta

TL; DR

Estás eliminando elementos de una copia del vector, no del std::vector que existe en el location encontrado del std::unordered_map.

Larga historia

Cuando llamas a auto vector = location->second; en Manager::removeCity estás haciendo una copia de ese vector dentro del alcance de la declaración if. Por lo tanto, sus cambios no se reflejarán en el contenedor al que se dirige. Solo su copia se verá afectada, y eso también queda fuera del alcance al final de la declaración if, por lo que todo lo que suceda si encuentra un location no se guardará en el estado de {{ Contenedor X5}}.

Puede solucionar esto simplemente llamando a location->second.clear() directamente o, si realmente desea darle otro nombre, use una referencia, p. auto& vec = location->second; vec.clear();. Tenga en cuenta que esto también se aplica al método Manager::addCity.

PD Me mantendría alejado de usar nombres de variables que sean los mismos que los de los contenedores o clases bien establecidas en el STL para evitar confusiones.

1
magikal 14 mar. 2021 a las 10:08