我有这段代码:
set<int>::iterator new_end =
set_difference(set1.begin(), set1.end(),
set2.begin(), set2.end(),
set1.begin());
set1.erase(new_end, set1.end);
它在视觉工作室中编译并运行良好。但是,在previous question中,人们声称set
的迭代器应该是const
。我没有在标准中看到类似的东西。有人可以告诉我它在哪里,或者这是明确定义的行为吗?
如果不是,请提供符合我需要的代码。有没有办法在不创建临时集的情况下执行此操作?
答案 0 :(得分:7)
您的代码违反了set_difference
的几个不变量。来自Josuttis Book的第420页:
你试图回写第一组,这是不允许的。您需要编写除源范围之外的其他位置 - 为此我们可以使用第三组:
std::set<int> set3;
std::set_difference(set1.begin(), set1.end(),
set2.begin(), set2.end(),
std::inserter(set3, set3.begin()));
std::inserter
的第二个参数是关于元素应插入位置的提示。然而,这只是一个提示,请放心,这些元素最终会出现在正确的位置。 set3
最初为空,因此begin()
是我们可以提供的唯一提示。
在致电set_difference
后,set3
将包含您尝试在原始代码中包含set1
的内容。如果您愿意,可以继续使用set3
或swap
set1
。
<强>更新强>
我不确定这种情况的表现,但如果您只想删除set1
中显示的set2
中的所有元素,您可以尝试:
for (std::set<int>::iterator i = set2.begin(); i != set2.end(); ++i)
{
set1.erase(*i);
}
答案 1 :(得分:5)
解决问题的一个建议:
std::set<int> tmp;
std::set_difference(set1.begin(), set1.end(),
set2.begin(), set2.end(),
std::inserter(tmp, tmp.begin()));
std::swap(tmp, set1);
如果不使用临时集(除了遍历容器并对单个元素进行擦除之外),我无法想到这样做的方法。
答案 2 :(得分:4)
不,不是。来自SGI STL Reference
此外,我不确定begin()是否可以用作OutputIterator,正如Nikolai N Fetissov所指出的那样。
答案 3 :(得分:1)
set_difference
的第五个参数应为OutputIterator
,请参阅documentation。
答案 4 :(得分:1)
C ++标准没有明确规定不允许分配给set迭代器,但它确实为set_difference指定“结果范围不应与原始范围重叠”(25.3.5.3)。
到目前为止,它可能对你有用,因为你对set1和set2的内容很幸运。