是下面的代码使用std :: set" legal" ;? [英] Is the following code using std::set "legal"?
问题描述
我有这个代码:
set<int>::iterator new_end =
set_difference(set1.begin(), set1.end(),
set2.begin(), set2.end(),
set1.begin());
set1.erase(new_end, set1.end);
它在visual studio中编译并运行良好。但是,在上一个问题中,人们表示 set
的迭代器应该是 const
。我在标准中没有看到这样的东西。有人可以告诉我它在哪里说,或者如果这是明确定义的行为?
It compiles and runs fine in visual studio. However, in a previous question, people stated that a set
's iterators are supposed to be const
. I don't see anything like that in the standard. Can someone tell me where it says that, or if this is well-defined behavior?
如果不是,请提供代码,我需要做的。有没有办法做到这一点,而不创建一个临时集?
If it's not, please provide code that does what I need. Is there a way to do this without creating a temporary set?
推荐答案
您的代码违反了一些不变量 set_difference
。从 Josuttis Book 的第420页起:
Your code violates a couple of the invariants for set_difference
. From page 420 of the Josuttis Book:
- 调用者必须确保目标范围足够大或使用插入迭代器。
- 目标范围不应与源范围重叠。
您尝试回写第一个集合,这是不允许的。您需要编写除源范围以外的其他位置 - 我们可以使用第三组:
You're trying to write back over the first set, which is not allowed. You need to write someplace other than the source ranges - for that we can use a third set:
std::set<int> set3;
std::set_difference(set1.begin(), set1.end(),
set2.begin(), set2.end(),
std::inserter(set3, set3.begin()));
std :: insertionter的第二个参数
是元素应插入的位置的提示。这只是一个提示,但是,放心,元素将最终在正确的地方。 set3
最初为空,因此 begin()
是我们可以提供的唯一提示。
The second argument to std::inserter
is a hint for where the elements should be inserted. It's only a hint, however, rest assured that the elements will end up in the right place. set3
is initially empty, so begin()
is about the only hint we can give.
调用 set_difference
后, set3
将包含您尝试创建的 set1
包含在原始代码中。您可以使用 set1
继续使用 set3
或 swap
如果您愿意。
After the call to set_difference
, set3
will contain what you tried to make set1
contain in your original code. You can go on using set3
or swap
it with set1
if you prefer.
更新:
如果你只想删除 set2
中出现的 set1
中的所有元素,你可以尝试:
I'm not sure about the performance of this, but if you just want to remove all elements from set1
that appear in set2
, you can try:
for (std::set<int>::iterator i = set2.begin(); i != set2.end(); ++i)
{
set1.erase(*i);
}
这篇关于是下面的代码使用std :: set" legal" ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!