• C++前后自增效率分析


    1、前自增/后自增操作符示例

    class Integer
    {
    public:
    	// ++i  first +1,then return new value
    	Integer &operator++()
    	{
    		value_ += 1;
    		return *this;
    	}
    
    	// i++  first save old value,then +1,last return old value
    	Integer operator++(int)
    	{
    		Integer old = *this;
    		value_ += 1;
    		return old;
    	}
    
    private:
    	int value_;
    };
    

    2、分别基于内置数据类型和自定义数据类型做测试

    #include <iostream>
    #include <vector>
    #include <windows.h>
    
    int main()
    {
    	const int sizeInt = 0x00fffffe;
    	const int sizeVec = 0x000ffffe;
    
    	LARGE_INTEGER frequency;
    	QueryPerformanceFrequency(&frequency);
    
    	{
    		int* testValue = new int[sizeInt];
    
    		LARGE_INTEGER start;
    		LARGE_INTEGER stop;
    		QueryPerformanceCounter(&start);
    		for (int i = 0; i < sizeInt; ++i)
    		{
    			testValue[i]++;
    		}
    		QueryPerformanceCounter(&stop);		
    
    		const auto interval = static_cast<double>(stop.QuadPart - start.QuadPart);
    		const auto timeSpan = interval / frequency.QuadPart * 1000.0; //ms
    		std::cout << "i++ " << sizeInt << " times takes " << timeSpan << "ms." << std::endl;
    
    		delete[] testValue;
    	}
    	{
    		int* testValue = new int[sizeInt];
    
    		LARGE_INTEGER start;
    		LARGE_INTEGER stop;
    		QueryPerformanceCounter(&start);
    		for (int i = 0; i < sizeInt; ++i)
    		{
    			++testValue[i];
    		}
    		QueryPerformanceCounter(&stop);		
    
    		const auto interval = static_cast<double>(stop.QuadPart - start.QuadPart);
    		const auto timeSpan = interval / frequency.QuadPart * 1000.0; //ms
    		std::cout << "++i " << sizeInt << " times takes " << timeSpan << "ms." << std::endl;
    
    		delete[] testValue;
    	}
    
    	{
    		const std::vector<int> testVec(sizeVec);
    		LARGE_INTEGER start;
    		LARGE_INTEGER stop;
    		QueryPerformanceCounter(&start);
    		for (auto iter = testVec.cbegin(); iter != testVec.cend(); iter++)
    		{
    		}
    		QueryPerformanceCounter(&stop);
    
    		const auto interval = static_cast<double>(stop.QuadPart - start.QuadPart);
    		const auto timeSpan = interval / frequency.QuadPart * 1000.0; //ms
    		std::cout << "iterator++ " << sizeVec << " times takes " << timeSpan << "ms." << std::endl;
    	}
    	{
    		const std::vector<int> testVec(sizeVec);
    		LARGE_INTEGER start;
    		LARGE_INTEGER stop;
    		QueryPerformanceCounter(&start);
    		for (auto iter = testVec.cbegin(); iter != testVec.cend(); ++iter)
    		{
    		}
    		QueryPerformanceCounter(&stop);
    
    		const auto interval = static_cast<double>(stop.QuadPart - start.QuadPart);
    		const auto timeSpan = interval / frequency.QuadPart * 1000.0; //ms
    		std::cout << "++iterator " << sizeVec << " times takes " << timeSpan << "ms." << std::endl;
    	}
    
    	return 0;
    }
    

    3、五次执行结果

    4、结果分析及结论

    从上面的执行结果可以看出来,对int类型的测试中前自增和后自增耗费时间基本不变;而对std::vector中iterator的测试显示,前自增所耗费的时间几乎是后自增的一半。这是因为,在后自增的操作中,会首先生成原始对象的一个副本,然后将副本中的值加1后返回给调用者,这样一来每执行一次后自增操作,就会增加一个对象副本,效率自然降低了。

    因此可以得出结论:对于C++内置类型的自增而言,前自增、后自增的效率相差不大;对于自定义类型(类、结构体)的自增操作而言,前自增的效率几乎比后自增大一倍。

    5、注意事项

    上述试验的循环代码如果在Release模式下会被C++编译器优化掉,因此需要在Debug模式下才能获得预期效果,但在实际项目中大概率是不会被编译器优化的。

  • 相关阅读:
    一个通过JSONP跨域调用WCF REST服务的例子(以jQuery为例)
    步步为营UML建模系列七、表图(Data model diagram)
    步步为营UML建模系列六、类图(Class diagram)
    WebEx
    使用Nancy和Simple.Data两个轻量级的框架打造一个分布式开发系统
    细说 ASP.NET控制HTTP缓存
    WCSF vs ASP.NET MVC
    使用KTM(内核事务管理器)进行文件事务处理
    .net 2.0下的OOXML神器:NPOI.OpenXml4Net
    为什么System.Attribute的GetHashCode方法需要如此设计?
  • 原文地址:https://www.cnblogs.com/xhubobo/p/12778403.html
Copyright © 2020-2023  润新知