根据this article,[ , ]
/\
1 [ , ]
/\
2 [3]
的一种可能的实现方式是
std::unique
但是,我没有得到迭代器比较的目的吗?为什么是template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last) {
if (!(*result == *first) && ++result != first) {
*result = std::move(*first);
}
}
return ++result;
}
而不仅仅是if (!(*result == *first) && ++result != first)
?比较两个迭代器的目的是什么?
答案 0 :(得分:2)
让我们将代码重写为更小的步骤(代码等同于问题中的代码-我只是将if语句分为两部分):
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
{
// are there elements to test?
if (first == last)
return last;
// there are elements so point result to the first one
ForwardIt result = first;
// then increment first and check if we are done
while (++first != last) {
// if the value of first is still the same as the value of result
// then restart the loop (incrementing first and checking if we are done)
// Notice that result isn't moved until the values differ
if (*result == *first)
continue;
// increment result and move the value of first to this new spot
// as long as they don't point to the same place
// So result is only moved when first points to a new (different) value
if (++result != first) {
*result = std::move(*first);
}
}
// return one past the end of the new (possibly shorter) range.
return ++result;
}
这里是一个例子:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 2 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第1步-首先递增,然后将first的值与result的值进行比较:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 2 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第2步-值不同,所以增加结果不同,但是现在它们指向同一位置,所以移动是多余的,我们不这样做
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 2 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第3步-首先递增,然后将first的值与result的值进行比较:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 2 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第4步-值相同,因此重新开始循环(先递增,然后将first的值与result的值进行比较):
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 2 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第5步-值不同,所以结果递增,它们指向不同的位置,因此将first的值移到result的值:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第6步-首先递增,然后将first的值与result的值进行比较:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 3 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第7步-值不同,所以结果递增,它们指向不同的位置,因此将first的值移到result的值:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第8步-首先递增,然后将first的值与result的值进行比较:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第9步-值相同,因此重新启动循环(先递增,然后将first的值与result的值进行比较):
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
步骤10-值相同,因此重新启动循环(先递增,然后将first的值与result的值进行比较):
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 4 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第11步-值不同,因此结果递增,它们指向不同的位置,因此将first的值移到result的值:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^ ^
first last
第12步-首先递增,而while循环结束,因为第一个和最后一个指向同一位置-然后在循环递增结果之后,使其成为唯一范围的新结束迭代器:
result
v
+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | 4 | 4 | 5 |
+-----+-----+-----+-----+-----+-----+-----+-----+
^
last&first
答案 1 :(得分:1)
如果您进行if(!(*result++ == *first))
,则始终在您的情况下增加result
。但是,如果!(*result == *first)
为假,则由于短路评估而无法评估条件的第二部分。
差异对“唯一”的含义至关重要。
答案 2 :(得分:0)
ForwardIt result = first;
while (++first != last) {
if (!(*result == *first) && ++result != first) {
*result = std::move(*first);
}
}
return ++result;
可以改写为
ForwardIt result = first;
// result is the last element different from previous values
// all the equal elements after result=first are useless
// *result = *first
// first is the last element examined
// determine largest range of useless elements
// *result = before(*first)
// i.e. result has the value of former value (before call) of element *first (current value of first)
// so first is the last element on which we know something
extend_useless_range:
// so range ]result,first] is useless
first++;
// now range ]result,first[ is useless
// and first is the first element yet to be examined
if (first == last) {
// ]result,last[ is useless
goto end_loop;
}
if (*result == *first) {
// *first is useless
// so range ]result,first] is useless
goto extend_useless_range;
}
// *first is useful
// range ]result,first[ is biggest useless range after result
result++;
// range [result,first[ is useless (and *first is useful)
if (result != first) {
// [result,first[ is nonempty
*result = std::move(*first);
// *result is useful and *first is useless (undetermined value)
// ]result,first] is useless
}
else {
// [result,first[ = ]result,first] = {} and is useless
}
// ]result,first] is useless
goto extend_useless_range;
end_loop: // ]result,last[ is useless
result++;
// [result,last[ is useless
return result;