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模式下才能獲得預期效果,但在實際項目中大概率是不會被編譯器優化的。

以上就是c++ 前自增/後自增操作符效率分析的詳細內容,更多關於c++ 前自增/後自增操作符的資料請關註WalkonNet其它相關文章!

推薦閱讀: