以下代码使用std :: set"legal"?

rlb*_*ond 3 c++ iterator stl set

我有这个代码:

set<int>::iterator new_end = 
                   set_difference(set1.begin(), set1.end(),
                                  set2.begin(), set2.end(),
                                  set1.begin());
set1.erase(new_end, set1.end);
Run Code Online (Sandbox Code Playgroud)

它在视觉工作室中编译并运行良好.然而,在之前的一个问题中,人们说set应该是一个迭代器const.我没有在标准中看到类似的东西.有人可以告诉我它在哪里,或者这是明确定义的行为吗?

如果不是,请提供符合我需要的代码.有没有办法在不创建临时集的情况下执行此操作?

Mic*_*fik 7

你的代码违反了几个不变量set_difference.从Josuttis书的第420页开始:

  • 调用者必须确保目标范围足够大或使用插入迭代器.
  • 目标范围不应与源范围重叠.

你试图回写第一组,这是不允许的.您需要编写除源范围之外的其他位置 - 为此我们可以使用第三组:

std::set<int> set3;
std::set_difference(set1.begin(), set1.end(),
                    set2.begin(), set2.end(),
                    std::inserter(set3, set3.begin()));
Run Code Online (Sandbox Code Playgroud)

第二个参数std::inserter是一个提示应该插入元素的位置.然而,这只是一个提示,请放心,这些元素最终会出现在正确的位置. set3最初是空的,所以begin()我们可以提供的唯一提示.

在调用之后set_difference,set3将包含您尝试set1在原始代码中包含的内容.如果您愿意,可以继续使用set3或使用swapset1.

更新:

我不知道这样的表现,但如果你只是想删除所有元素set1出现在set2,你可以试试:

for (std::set<int>::iterator i = set2.begin(); i != set2.end(); ++i)
{
    set1.erase(*i);
}
Run Code Online (Sandbox Code Playgroud)


CAd*_*ker 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);
Run Code Online (Sandbox Code Playgroud)

如果不使用临时集(除了迭代容器并对单个元素进行擦除),我无法想到一种方法.