在C++中返回unique()函数

3
我发现了下面这个函数,它对由main()传递下来的数组进行排序、去重,并返回唯一元素的数量。最后一部分让我很难理解。
int reduce(long ar[], int n) {
  sort(ar, ar + n);
  return unique(ar, ar + n) - ar; // ??? 
}

据我理解,unique() 返回一个指针,它指向存储数组中唯一值的段的末尾。但是我不明白为什么从迭代器中减去数组名称会导致一个等于唯一元素数量的整数,或者为什么不能将unique(ar, ar+n)强制转换为int来实现相同的结果。

1
我不明白为什么如果unique()返回一个指针,那么reduce()函数为什么会返回int而不是int *。 - Mihai8
因为返回语句所评估的不是指针,而是两个指针之间的差异。 - jogojapan
@user1929959:两个指向同一序列的指针之间的差值就是它们之间的元素数量。 - IInspectable
看到STL中独特的函数会很有生产力。 - Mihai8
@user1929959 这是标准库中的 unique 函数。 - jogojapan
显示剩余2条评论
2个回答

5

假设你有这样一个数组:

{1, 2, 2, 3, 4, 4, 5}

调用 std::unique 后,您很可能会得到这样的结果(感谢 Nawaz),在新结尾后面的元素仍然保持之前的状态:
{1, 2, 3, 4, 5, 4, 5}
               ^

std::unique返回指向数组新结尾的迭代器,因此箭头所在的位置。从那里开始,逻辑上讲减去数组开头将返回唯一元素的数量。如果您想更加明确,可以使用return std::distance(ar,std::unique(ar,ar + n));,这也适用于迭代器不支持减法的情况。


处理后的数组是错误的。std::unique 不会将重复元素与 结尾后的元素交换。我的意思是,它可能只会返回 {1, 2, 3, 4, 5, | 4, 5},其中 | 标记了新的结尾。 - Nawaz
@Nawaz,我假设你在最后是指“4, 2”,但是我不确定它们的确切作用,而且我认为这些重复项在任何情况下都没有用处(至少在这里)。重复项的顺序取决于实现方式,对吧?无论如何,我会更明确地表达我的意思。 - chris
1
@chris:规范没有关于新结尾后的元素的说明,我认为这意味着它们会保留在那里,就像我在之前的评论中展示的那样。 - Nawaz
@Nawaz,哦,我现在明白你的意思了。这与cppreference的示例一致。现在描述更有意义了。我只是因为太累而变得迟钝了。 - chris
1
@Nawaz,感谢你一直陪伴着我。我花了很长时间才正确理解你的意思,从你的角度来看,这有点令人沮丧。 - chris

5

为什么不能将unique(ar,ar + n)强制转换为int以达到相同的结果。

因为,如您所说,unique返回一个指针。 指针是内存地址,而不是索引。 因此,将指针强制转换为int是没有意义的。

为什么从迭代器中减去数组名称会导致一个等于唯一元素数量的整数

减去两个指针(指向同一个数组)将计算它们之间的元素数。*


* 如下面的评论中@Nawaz指出的那样,这个结果是有符号的。所以 (p1-p2)== -(p2-p1)


2
@Nawaz:没错!我在脚注中标明了你的贡献 ;) - Oliver Charlesworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接