在C++编程中,经常会涉及两个容器之间的数据拷贝(如数组之间元素的拷贝),常规的做法一般都是用for循环逐个元素进行拷贝。在数据量不大的情况下还可以,如果数据量比较大,效率则会比较低下。
而 std::copy 就是一个专门用于容器间拷贝的函数,其效率是优于使用for循环的!但是需要注意的是:std::copy 只负责复制,不负责申请空间,所以复制前必须有足够的空间。
而 std::copy_if,则是在 std::copy 执行的时候,可以让你有机会对源容器的元素进行判断,从而决定哪些元素可以拷贝,哪些不拷贝!
在实验之前,我们先了解一下 iota 这个函数(iota 可用于生成连续的数字序列)
#include <iostream>
#include <numeric>//std::iota
int main()
{
int numbers[10];
int startVal = 100;//start value
std::iota(numbers, numbers + 10, startVal);
std::cout << "Elements are:";
for (auto i : numbers)
std::cout << ' ' << i;
std::cout << '\n';
}
输出结果:
Elements are: 100 101 102 103 104 105 106 107 108 109
#include <iostream>
#include <numeric>//std::iota
#include <vector>
#include <algorithm>
int main()
{
//iota 可用于生成连续的数字序列
std::vector<int> fromVector(10);
std::iota(fromVector.begin(), fromVector.end(), 0);
//
std::vector<int> toVector;
std::copy(fromVector.begin(), fromVector.end(), std::back_inserter(toVector));
#if 0
// 或者
std::vector<int> toVector(fromVector.size());
std::copy(fromVector.begin(), fromVector.end(), toVector.begin());
// 无论哪种方式,实际结果都相当于
std::vector<int> toVector = fromVector;
#endif
std::cout << "toVector contains: ";
std::copy(toVector.begin(), toVector.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
//把fromVector中偶数拷贝到toVector
std::cout << "even numbers in toVector are: ";
std::copy_if(toVector.begin(), toVector.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int x) { return std::fmod(x, 2) == 0; });
std::cout << '\n';
//把fromVector中是3的倍数拷贝到toVector
std::cout << "toVector contains these multiples of 3:\n";
toVector.clear();
std::copy_if(fromVector.begin(), fromVector.end(),
std::back_inserter(toVector),
[](int x) { return std::fmod(x, 3) == 0; });
for (int x : toVector)
std::cout << x << ' ';
std::cout << '\n';
return 0;
}
输出结果:
toVector contains: 0 1 2 3 4 5 6 7 8 9
even numbers in toVector are: 0 2 4 6 8
toVector contains these multiples of 3:
0 3 6 9
#include <iostream>
#include <numeric>//std::iota
#include <vector>
#include <algorithm>
#include <chrono>
class timelapsed
{
public:
timelapsed(std::string&& name)
: m_name(std::forward<std::string>(name))
, m_now(std::chrono::high_resolution_clock::now()) { }
~timelapsed()
{
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> dur(end - m_now);
std::cout << m_name << " : " << dur.count() << " seconds ##### \n";
}
private:
std::string m_name;
std::chrono::time_point<std::chrono::high_resolution_clock> m_now;
};
int main()
{
int container_size = 1000000;
std::vector<int> vectorFrom(container_size);
std::iota(fromVector.begin(), fromVector.end(), 0);
int* vectorTo = new int[vectorFrom.size()];
{
timelapsed _timelapsed("use copy");
std::copy(vectorFrom.begin(), vectorFrom.end(), vectorTo);
}
{
timelapsed _timelapsed("use for");
for (int i = 0; i < container_size; i++)
{
vectorTo[i] = vectorFrom[i];
}
}
return 0;
}
性能测试结果:
use copy : 0.0001559 seconds #####
use for : 0.0108972 seconds #####
可以看到,在拷贝大数据量时,std:copy 的效率是远高于使用 for 循环的!!!