a std::set中元素的键值是const有充分理由的。修改它们可能会破坏顺序,这对于至关重要std::set。
因此,解决方案是擦除迭代器并使用key插入一个新的迭代器*it - sub。请注意,std::set::erase()返回一个新的迭代器,在您的情况下必须使用该迭代器以保持while循环正常运行。
#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 }
在coliru上进行现场演示
std::set通常,对它进行迭代时的更改不是问题,但可能导致细微的问题。
最重要的事实是所有使用过的迭代器必须保持完整或不再使用。(这就是为什么将擦除元素的当前迭代器分配为返回值std::set::erase()是完整迭代器或set结束的原因。)
当然,也可以在当前迭代器后面插入元素。虽然这不是一个问题,但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 }
在coliru上进行现场演示