Giá trị chính của các yếu tố trong một std::setlà constvì một lý do tốt. Sửa đổi chúng có thể phá hủy thứ tự cần thiết cho a std::set.
Do đó, giải pháp là xóa iterator và chèn một cái mới bằng khóa *it - sub. Xin lưu ý rằng std::set::erase()trả về một trình vòng lặp mới phải được sử dụng trong trường hợp của bạn để giữ cho vòng lặp while hoạt động bình thường.
#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';
}
Đầu ra:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
Demo trực tiếp trên coliru
Thay đổi std::settrong khi lặp đi lặp lại nó không phải là một vấn đề nói chung nhưng có thể gây ra các vấn đề tinh tế.
Thực tế quan trọng nhất là tất cả các trình vòng lặp đã sử dụng phải được giữ nguyên hoặc không được sử dụng nữa. (Đó là lý do tại sao bộ lặp hiện tại của phần tử xóa được gán với giá trị trả về std::set::erase()là bộ lặp nguyên vẹn hoặc phần cuối của bộ.)
Tất nhiên, các phần tử có thể được chèn vào phía sau trình lặp hiện tại. Mặc dù đây không phải là vấn đề liên quan đến việc std::setnó có thể phá vỡ vòng lặp của ví dụ trên của tôi.
Để chứng minh, tôi đã thay đổi mẫu trên một chút. Xin lưu ý rằng tôi đã thêm một bộ đếm bổ sung để cấp phép chấm dứt vòng lặp:
#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';
}
Đầu ra:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
Demo trực tiếp trên coliru