A의 원소의 키 값 std::set입니다 const좋은 이유. 수정하면에 필수적인 순서가 손상 될 수 있습니다 std::set.
따라서 해결책은 반복자를 지우고 키를 사용하여 새 반복자를 삽입하는 것입니다 *it - sub. std::set::erase()while 루프가 제대로 작동하도록하려면 새 iterator 를 반환해야합니다.
#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';
}
산출:
test: { 11, 12, 13, 14, 15 }
test: { 1, 2, 3, 4, 5 }
콜리 루 라이브 데모
std::set반복 하는 동안의 변경 은 일반적으로 문제가 아니지만 미묘한 문제를 일으킬 수 있습니다.
가장 중요한 사실은 사용 된 모든 반복자가 그대로 유지되거나 더 이상 사용되지 않아야한다는 것입니다. (따라서 지우기 요소의 현재 반복자에 반환 값이 std::set::erase()손상되지 않은 반복자이거나 세트의 끝인 것이 지정됩니다.)
물론 현재 반복자 뒤에 요소를 삽입 할 수 있습니다. 이것은 이것에 관한 문제는 아니지만 std::set위 예제의 루프를 깨뜨릴 수 있습니다.
이를 입증하기 위해 위의 샘플을 약간 변경했습니다. 루프 종료를 허용하기 위해 카운터를 추가했습니다.
#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';
}
산출:
test: { 11, 12, 13, 14, 15 }
test: { 23, 24, 25, 31, 32 }
콜리 루 라이브 데모