在C++编程中,经常会涉及两个容器之间的数据拷贝(如数组之间元素的拷贝),常规的做法一般都是用for循环逐个元素进行拷贝。在数据量不大的情况下还可以,如果数据量比较大,效率则会比较低下。

而 std::copy 就是一个专门用于容器间拷贝的函数,其效率是优于使用for循环的!但是需要注意的是:std::copy 只负责复制,不负责申请空间,所以复制前必须有足够的空间。

而 std::copy_if,则是在 std::copy 执行的时候,可以让你有机会对源容器的元素进行判断,从而决定哪些元素可以拷贝,哪些不拷贝!

在实验之前,我们先了解一下 iota 这个函数(iota 可用于生成连续的数字序列)

std::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

std::copy 和 std::copy_if 的示例程序
#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

std::copy 与 for 性能对比
#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 循环的!!!

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐