Schlüsselwerte von Elementen in a std::sethaben consteinen guten Grund. Wenn Sie sie ändern, kann dies die Reihenfolge zerstören, die für a std::set.
Daher besteht die Lösung darin, den Iterator zu löschen und einen neuen mit Schlüssel einzufügen *it - sub. Bitte beachten Sie, dass std::set::erase()ein neuer Iterator zurückgegeben wird, der in Ihrem Fall verwendet werden muss, damit die while-Schleife ordnungsgemäß funktioniert.
#include<iostream>
#include<set>
template <typename T>
std::ostream& operator<<(std::ostream &out, const std::set<T> &values)
{
const char *sep = "{ ";
for (const T &value : values) { out << sep << value; sep = ", "; }
return out << " }";
}
int main()
{
std::set<int> test{ 11, 12, 13, 14, 15 };
std::cout << "test: " << test << '\n';
const int sub = 10;
std::set<int>::iterator iter = test.begin();
while (iter != test.end()) {
const int value = *iter;
iter = test.erase(iter);
test.insert(value - sub);
}
std::cout << "test: " << test << '\n';
}
Ausgabe:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Live-Demo auf coliru
Änderungen std::setwährend der Iteration sind im Allgemeinen kein Problem, können jedoch subtile Probleme verursachen.
Die wichtigste Tatsache ist, dass alle verwendeten Iteratoren intakt bleiben müssen oder nicht mehr verwendet werden dürfen. (Aus diesem Grund wird dem aktuellen Iterator des Löschelements der Rückgabewert zugewiesen, dessen Rückgabewert std::set::erase()entweder ein intakter Iterator oder das Ende der Menge ist.)
Natürlich können auch Elemente hinter dem aktuellen Iterator eingefügt werden. Dies ist zwar kein Problem, std::setkann aber die Schleife meines obigen Beispiels durchbrechen.
Um dies zu demonstrieren, habe ich das obige Beispiel ein wenig geändert. Bitte beachten Sie, dass ich einen zusätzlichen Zähler hinzugefügt habe, um die Beendigung der Schleife zu gewähren:
#include<iostream>
#include<set>
template <typename T>
std::ostream& operator<<(std::ostream &out, const std::set<T> &values)
{
const char *sep = "{ ";
for (const T &value : values) { out << sep << value; sep = ", "; }
return out << " }";
}
int main()
{
std::set<int> test{ 11, 12, 13, 14, 15 };
std::cout << "test: " << test << '\n';
const int add = 10;
std::set<int>::iterator iter = test.begin();
int n = 7;
while (iter != test.end()) {
if (n-- > 0) {
const int value = *iter;
iter = test.erase(iter);
test.insert(value + add);
} else ++iter;
}
std::cout << "test: " << test << '\n';
}
Ausgabe:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Live-Demo auf coliru