2013-08-18 9 views
11

Wenn ich über eine std::unordered_map mit dem Bereich für Schleife zweimal durchlaufen, ist die Reihenfolge garantiert gleich?Ist für (auto i: unordered_map) garantiert, jedes Mal die gleiche Reihenfolge zu haben?

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 += ");" 

Im obigen Beispiel sollte die resultierende Zeichenfolge in dieser Form sein. Daher ist es wichtig, dass beide Male die Reihenfolge der Iterationen gleich ist.

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

Ist dies in C++ garantiert?

+0

Bitte sagen Sie mir, dass Sie irgendwo gegen SQL-Injektion schützen. –

+0

@D.Shawley Ich nicht im Moment. Aber es geht um die Rettung eines Computerspiels. Ich code das Spiel und es gibt keine Möglichkeit, SQL von außerhalb des Anwendungscodes überhaupt zu injizieren. – danijar

+0

Ich krümme mich einfach jedes Mal, dass ich SQL-Strings durch Raw-String-Verkettung erstellen. –

Antwort

19

Die Iterationsreihenfolge ungeordneter assoziativer Container ist nur, wenn ändern Wiederherstellung als Ergebnis einer Mutationsoperation (wie in C++ 11 23.2.5/8 beschrieben). Sie ändern den Container zwischen Iterationen nicht, sodass sich die Reihenfolge nicht ändert.

Obwohl in der Spezifikation nicht explizit angegeben wird, dass das erneute Speichern zu keinem anderen Zeitpunkt ausgeführt werden kann, würde dies alle Iteratoren über den Container ungültig machen, sodass eine Iteration überhaupt nicht möglich ist.

17

Warum nicht zusammen bauen?

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 ")"; 

Sieht netter zu imo.

Bitte beachten Sie, wenn dieser Abschnitt Leistung entscheidend ist, könnte man erwägen den String Bauprozess mit std :: Optimierung string als here gezeigt, obwohl es not clear how much that might help

+1

Verwenden Sie stattdessen "ostringstream", aber dies ist der bessere Ansatz. –

+0

@ D.Shawley ja wahrscheinlich, wenn dies ein leistungsintensiver Abschnitt ist. Sonst könnte das aus Gründen der Lesbarkeit besser sein, so wie ich mich hauptsächlich auf die Lösung seines Problems konzentrierte. –

+0

Großartig! Ich könnte das sogar abschneiden, weil der erste Schlüssel und der erste Wert angegeben sind. 'std :: string keys =" id ", Werte = to_string (Id); für (auto i: serialisierte) Schlüssel + = "," + i.erst, Werte + = "," + i.second; '. – danijar