Nilai-nilai kunci elemen dalam std::setadalah constuntuk alasan yang bagus. Mengubah mereka dapat merusak urutan yang penting untuk a std::set.
Oleh karena itu, solusinya adalah menghapus iterator dan memasukkan yang baru dengan kunci *it - sub. Harap perhatikan bahwa std::set::erase()mengembalikan iterator baru yang harus digunakan dalam kasus Anda agar loop sementara berfungsi dengan baik.
#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';
}
Keluaran:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Demo langsung di coliru
Perubahan pada std::setsaat iterasi itu bukan masalah secara umum tetapi dapat menyebabkan masalah halus.
Fakta yang paling penting adalah bahwa semua iterator yang digunakan harus tetap utuh atau tidak dapat digunakan lagi. (Itulah sebabnya iterator saat ini dari elemen erase ditetapkan dengan nilai pengembalian std::set::erase()yang mana merupakan iterator utuh atau akhir set.)
Tentu saja, elemen dapat dimasukkan juga di belakang iterator saat ini. Meskipun ini bukan masalah mengenai hal std::setitu dapat memutus loop dari contoh saya di atas.
Untuk menunjukkannya, saya mengubah sampel di atas sedikit. Harap perhatikan bahwa saya menambahkan penghitung tambahan untuk memberikan penghentian loop:
#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';
}
Keluaran:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Demo langsung di coliru