<algorithm>文件中copy、copy_n 、copy_if 、copy_backward算法学习

学习内容

本节学习内部的算法copy、copy_n 、copy_if 、copy_backward

copy(C++98引入)

功能: 将原序列范围内的所有元素,按照顺序拷贝到目标序列

原型:

template < class InputIt , class OutputIt >

OutputIt copy ( InputIt first , InputIt last , OutputIt d_first);

参数解析:

first / last : 原序列的起始/终止迭代器,拷贝范围为 [first , last)

d_first : 目标序列的起始迭代器,拷贝从该位置开始

返回值:目标序列中最后一个拷贝元素的下一个迭代器(end())

用法:

cpp 复制代码
vector<int> src = { 1 ,2, 3, 4 ,5 };
vector<int> dst(src.size());
//返回it的end()
auto it = copy ( src.begin(),src.end(),dst.begin());

copy_n (C++11引入)

功能:从原序列的起始位置first开始,拷贝N个元素到目标序列(从d_first开始),无需指定原序列结束位置

原型:

template <class InputIt , class Size , class OutputIt>

OutputIt copy_n( InputIt first , Size n ,OutputIt d_first );

参数解析:

first: 原序列的起始迭代器,拷贝范围为 first ,first + n

n : 需要拷贝的元素的数量

d_first : 目标序列的起始迭代器,拷贝从该位置开始

返回值:目标序列中最后一个拷贝元素的下一个迭代器(end())

用法:

cpp 复制代码
vector<int> src = { 1 ,2, 3, 4 ,5 };
vector<int> dst(3);

auto it = copy_n( src.begin() , 3 , dst.begin());

copy_if (C++11引入)

功能:遍历原序列[ first , last ),将满足自定义条件的元素,按从左到右顺序拷贝到目标序列(从d_first开始),带筛选逻辑的拷贝

原型:

template < class InputIt , class OutputIt , class UnaryPredicate>

OutputIt copy ( InputIt first , InputIt last , OutputIt d_first , UnaryPredicate p);

参数解析:

first / last : 原序列的起始/终止迭代器,拷贝范围为 [first , last)

d_first : 目标序列的起始迭代器,拷贝从该位置开始

p : 单参函数(函数指针,函数对象,lambda),接受一个原序列元素,返回bool

返回值:目标序列中最后一个拷贝元素的下一个迭代器(end())

用法:

cpp 复制代码
vector<int> src = { 1 ,2, 3, 4 ,5 };
vector<int> dst(3);
auto it = copy_if( src.begin() , src.end() , dst.begin() , [](int ele) { return ele > 2 ; };

copy_backward(C++98引入)

功能:将原序列[ first ,last )范围内所有元素,按照逆序( last -1 , first )拷贝到目标序列的后向位置 ( d_last -1开始),解决原/目标序列重叠时拷贝覆盖问题

原型:

template < class BidirectionalIt1 , class BidirectionalIt2 >

BidirectionalIt2 copy_backward( BidirectionalIt1 first , BidirectionalIt1 last , BirectionalIt2 d_last );

参数解析:

first / last : 原序列的起始/终止迭代器,拷贝范围为 [first , last)(要求为双向迭代器)

d_last : 目标序列的终止迭代器,拷贝从 d_last-1 开始 (要求为双向迭代器)

返回值:目标序列中第一个拷贝元素的迭代器(begin())

用法:

cpp 复制代码
//覆盖问题,操作同一个队列
vector<int> src = { 1 ,2, 3, 4 ,5 ,0,0};
auto it = copy_backward( src.begin(),src.end(), src.end());

vector<int> vec = { 6, 6, 8};
vector<int> dst(3);
auto iter = copy_backward( vec.begin(),vec.begin()+3 , dst.end());

C++14无重大变化

C++17 并行化重载+迭代器约束强化

1、为四个算法均新增了带执行策略的重载,支持串行、并行、并行向量化三种指定方式(均在第一个参数位置)

执行策略类型:

std::execution:seq : 串行执行

std::execution::par:并行执行

std::execution::par_unseq: 并行向量化执行

适用场景: 当拷贝元素数量巨大时,使用并行可减少拷贝耗时

cpp 复制代码
//包含头文件 <execution>
vector<int> src(1000000,1);
vector<int> dst(1000000);

copy(exection::par , src.begin() , src.end() , dst.begin() );
copy_n( exection::par , src.begin(),500000, dst.begin());
copy_if( exection::par,src.begin(),src.end() ,dst.begin() , [](int x) { return x > 0 ; } );
copy_backward (exection::par , src.begin() , src.end() , dst.end());

2、迭代器约束编译器显式化

通过static_assert和迭代器特性检测,让四个算法迭代器约束从运行时未定义变成编译期显式报错

例如copy_backward只能使用双向迭代器,这样在编译期就可以检测迭代器是否为双向

3、copy_if的一元函数支持可移动类型 (接受const& / && 元素)

C++20 增加两个特性:constexpr和Concepts,实现编译期运行和迭代器的强类型约束

1、四个算法均支持constexpr重载版本,在编译期可完成拷贝

编译期执行条件:原/目标序列指向编译期可访问内存(constexpr、std::array); 元素类型为字面量 ;若为copy_if,则参数类型必须是constexpr可调用对象

constexpr array<int,4> src = { 1 ,2 ,3 ,4 };

constexpr array<int,4> dst = <>{

array<int,4> tmp = {0};

constexpr copy (src.begin() , src.end() , tmp.begin() );

return tmp;

}();

2、迭代器约束基于Concepts强类型化

四种算法原型中的 class InputIt ,class OutputIt,约束为std::input_iterator , std::output_interator等,copy_backward中双向迭代器的目标约束为std::bidirectional_iterator

3、copy_n中的n支持无符号类型大小

C++23 底层性能优化

1、连续内存迭代器特化优化:对访问随机迭代器(vector/array等)做编译期特化,直接调用内存块拷贝,替代逐元素拷贝

2、copy_backward重叠检测优化:检测若无重叠情况,自动将函数优化为copy

3、空范围拷贝:对原序列的first==last的或copy_n中n=0的情况,直接返回目标迭代器

4、copy_if中单参函数的noexcept约束:明确抛出异常时行为

相关推荐
Ruihong2 小时前
Vue withDefaults 转 React:VuReact 怎么处理?
vue.js·react.js·面试
kyriewen3 小时前
别再这样写 async/await 了:我在 Code Review 中见过最多的 8 个错误
前端·javascript·面试
BothSavage7 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn7 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽8 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
郝学胜_神的一滴9 小时前
CMake 034:生成器表达式:解耦构建时序、精简分支逻辑的终极利器
c++·cmake
云技纵横9 小时前
一个 @Async,把 @Transactional 的事务边界打穿了
后端·面试
想要成为糕糕手9 小时前
Harness Engineering:大模型时代的“马鞍”——从记忆层开始,让AI真正为你所用
面试·ai编程·claude
kyriewen1 天前
我手写了一个 EventEmitter,面试官追问了 6 个问题——第 4 个我没答上来
前端·javascript·面试