命名空间
变体
操作

std::unique_copy

来自 cppreference.com
< cpp‎ | algorithm
 
 
算法库
受约束算法和范围上的算法 (C++20)
受约束算法,例如 ranges::copy, ranges::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 - 要使用的执行策略。有关详细信息,请参阅 execution policy
p - 二元谓词,如果元素应被视为相等,则返回 ​true

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

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

虽然签名不需要具有 const &,但该函数不得修改传递给它的对象,并且必须能够接受类型 (可能是 const) Type1Type2 的所有值,无论 值类别 如何 (因此,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 的值类型既不是 CopyConstructible 也不是 CopyAssignable,则可能会产生性能成本。

[编辑] 异常

具有名为 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++ 标准。

DR 应用于 发布的行为 正确行为
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
有条件地需要

[编辑] 参见

查找前两个相邻且相等 (或满足给定谓词) 的项目
(函数模板) [编辑]
从一个范围内删除连续的重复元素
(函数模板) [编辑]
将元素范围复制到新的位置
(函数模板) [编辑]
创建一些元素范围的副本,其中不包含连续的重复项
(niebloid)[编辑]