• C++11 std::copy、std::copy_if 用法小结


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

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

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

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

    std::iota 的示例程序

    #include 
    #include //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';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    输出结果:
    Elements are: 100 101 102 103 104 105 106 107 108 109

    std::copy 和 std::copy_if 的示例程序

    #include 
    #include //std::iota
    #include 
    #include 
    
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    输出结果:
    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 
    #include //std::iota
    #include 
    #include 
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    性能测试结果:
    use copy : 0.0001559 seconds #####
    use for : 0.0108972 seconds #####
    可以看到,在拷贝大数据量时,std:copy 的效率是远高于使用 for 循环的!!!

  • 相关阅读:
    排序算法(Java版)
    HarmonyOS Next鸿蒙NDK使用示例
    pycharm的debug,你知道每个按钮对应哪个功能吗?
    各大搜索引擎的User-Agent
    【洛谷 P5250】【深基17.例5】木材仓库 题解(集合+upper_bound)
    【算法详解】如何使用递归,递归使用的技巧详解
    k8s开放接口
    有些段子,外行人根本看不懂,只有程序员看了会狂笑不止
    lenovo联想笔记本ThinkPad P16V Gen 1(21FC,21FD)原装出厂Win11系统
    全面战争三国 mod 修改
  • 原文地址:https://blog.csdn.net/hellokandy/article/details/125999765