web-dev-qa-db-fra.com

Est-ce que pour (auto i: unordered_map) est garanti d'avoir le même ordre à chaque fois?

Lorsque j'itère sur un std::unordered_map avec la plage basée sur la boucle deux fois, l'ordre est-il garanti égal?

std::unordered_map<std::string, std::string> map;

std::string query = "INSERT INTO table (";
bool first = true;
for(auto i : map)
{
    if(first) first = false;
    else query += ", ";
    query += i.first;
}
query += ") ";

query += "VALUES (";
first = true;
for(auto i : map)
{
    if(first) first = false;
    else query += ", ";
    query += i.second;
}
query += ");"

Dans l'exemple ci-dessus, la chaîne résultante doit être sous cette forme. Par conséquent, il est important que les deux fois, l'ordre d'itération soit le même.

INSERT INTO table (key1, key2, key3) VALUES (value1, value2, value3);

Est-ce garanti en C++?

21
danijar

L'ordre d'itération des conteneurs associatifs non ordonnés ne peut changer que lors du réhachage à la suite d'une opération de mutation (comme décrit dans C++ 11 23.2.5/8). Vous ne modifiez pas le conteneur entre les itérations, donc l'ordre ne changera pas.

Bien que la spécification n'indique pas explicitement que le rehachage ne peut se produire à aucun autre moment, cela invaliderait tous les itérateurs sur le conteneur, rendant toute itération impossible.

28
Mike Seymour

Pourquoi ne pas les construire ensemble?

for(auto i : map)
{
    if(first) first = false;
    else{
        keys += ", ";
        query += ", ";
    }
    keys += i.first;

    values += i.second;
}

std::string query = "INSERT INTO table (" + keys + ") VALUES (" + values ")";

Ça a l'air plus beau aussi.

Veuillez noter que si cette section est critique pour les performances, vous pouvez envisager d'optimiser le processus de construction de chaînes avec std :: stringstream comme indiqué ici , bien que ce soit pas clair combien cela pourrait aider =

17
Karthik T