学习内容
本节学习内部的算法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约束:明确抛出异常时行为