命名空间
变体
操作

std::unique_copy

来自 cppreference.cn
< cpp‎ | 算法
 
 
算法库
有约束算法与针对范围的算法 (C++20)
有约束的算法,例如 ranges::copyranges::sort 等……
执行策略 (C++17)
排序及相关操作
划分操作
排序操作
二分搜索操作
(于已划分范围上)
集合操作(于已排序范围上)
归并操作(于已排序范围上)
堆操作
最小/最大值操作
(C++11)
(C++17)
字典序比较操作
排列操作
C 库
数值操作
未初始化内存上的操作
 
定义于头文件 <algorithm>
template< class InputIt, class OutputIt >
OutputIt unique_copy( InputIt first, InputIt last, OutputIt d_first );
(1) (C++20 起为 constexpr)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >

ForwardIt2 unique_copy( ExecutionPolicy&& policy, ForwardIt1 first,

                        ForwardIt1 last, ForwardIt2 d_first );
(2) (C++17 起)
template< class InputIt, class OutputIt, class BinaryPred >

OutputIt unique_copy( InputIt first, InputIt last,

                      OutputIt d_first, BinaryPred p );
(3) (C++20 起为 constexpr)
template< class ExecutionPolicy, class ForwardIt1,

          class ForwardIt2, class BinaryPred >
ForwardIt2 unique_copy( ExecutionPolicy&& policy,
                        ForwardIt1 first, ForwardIt1 last,

                        ForwardIt2 d_first, BinaryPred p );
(4) (C++17 起)

将范围 [firstlast) 中的元素复制到从 d_first 开始的另一个范围,使得没有连续相等的元素。只复制每组相等元素的第一个元素。

1) 使用 operator== 比较元素。
如果 operator== 未建立等价关系,则行为未定义。
3) 使用给定二元谓词 p 比较元素。
如果 p 未建立等价关系,则行为未定义。
2,4)(1,3),但按 policy 执行。
仅当满足所有以下条件时,这些重载才参与重载决议

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>true

(C++20 前)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true

(C++20 起)

如果 *d_first = *first 无效(C++20 前)*first 不能写入d_first(C++20 起),则程序非良构。

如果源范围和目标范围重叠,则行为未定义。

给定 TInputIt 的值类型,如果重载 (1)(3) 不满足以下所有条件,则行为未定义:

(C++20 前)
(C++20 起)

目录

[编辑] 参数

first, last - 定义要处理元素的源范围的迭代器对
d_first - 目标范围的开头
policy - 要使用的 执行策略
p - 二元谓词,如果元素应被视为相等,则返回 true。

谓词函数的签名应等效于以下内容:

 bool pred(const Type1 &a, const Type2 &b);

虽然签名不需要有 const &,但函数不得修改传递给它的对象,并且必须能够接受 Type1Type2 类型(可能为 const)的所有值,无论值类别如何(因此,不允许 Type1 &,除非对于 Type1,移动等同于复制,否则也不允许 Type1(C++11 起))。
类型 Type1Type2 必须使得类型为 InputIt 的对象可以解引用,然后隐式转换为它们两者。

类型要求
-
InputIt 必须满足 LegacyInputIterator 的要求。
-
OutputIt 必须满足 LegacyOutputIterator 的要求。
-
ForwardIt1, ForwardIt2 必须满足 LegacyForwardIterator 的要求。

[编辑] 返回值

指向最后一个写入元素之后的元素的输出迭代器。

[编辑] 复杂度

给定 N 作为 std::distance(first, last)

1,2) 使用 operator== 进行恰好 max(0,N-1) 次比较。
3,4) 恰好 max(0,N-1) 次谓词 p 的应用。

对于重载 (2,4),如果 ForwardIt1 的值类型不是既 CopyConstructibleCopyAssignable,则可能存在性能开销。

[编辑] 异常

带有模板参数 ExecutionPolicy 的重载按如下方式报告错误

  • 如果作为算法一部分调用的函数执行抛出异常,并且 ExecutionPolicy标准策略之一,则调用 std::terminate。对于任何其他 ExecutionPolicy,行为由实现定义。
  • 如果算法未能分配内存,则抛出 std::bad_alloc

[编辑] 可能的实现

另见 libstdc++libc++ 中的实现。

[编辑] 注意

如果 InputIt 满足 LegacyForwardIterator,则此函数会重新读取输入以检测重复项。

否则,如果 OutputIt 满足 LegacyForwardIterator,并且 InputIt 的值类型与 OutputIt 的值类型相同,则此函数会将 *d_first*first 进行比较。

否则,此函数会将 *first 与本地元素副本进行比较。

[编辑] 示例

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
 
int main()
{
    std::string s1 {"A string with mmmany letters!"};
    std::cout << "Before: " << s1 << '\n';
 
    std::string s2;
    std::unique_copy(s1.begin(), s1.end(), std::back_inserter(s2),
                     [](char c1, char c2) { return c1 == 'm' && 'm' == c2; });
 
    std::cout << "After:  " << s2 << '\n';
}

输出

Before: A string with mmmany letters!
After:  A string with many letters!

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 239 C++98 谓词被应用 std::distance(first, last) 少应用一次
(对于非空范围)
LWG 241 C++98 InputIt 的值类型不需要是 CopyConstructible 有条件地要求
LWG 538 C++98 InputIt 的值类型不需要是 CopyAssignable 有条件地要求
LWG 2439 C++98 InputIt 的值类型不需要是
CopyConstructible,如果 OutputItLegacyForwardIterator
有条件地要求

[编辑] 参阅

寻找第一对相等的(或满足给定谓词的)相邻项
(函数模板) [编辑]
移除一个范围中的连续重复元素
(函数模板) [编辑]
将一个范围的元素复制到一个新位置
(函数模板) [编辑]
创建一个不含连续重复元素的某个元素范围的副本
(算法函数对象)[编辑]