Is there a performance difference between i++ and ++i in C++?

前端 未结 17 1955
臣服心动
臣服心动 2020-11-21 17:15

We have the question is there a performance difference between i++ and ++i in C?

What\'s the answer for C++?

17条回答
  •  南笙
    南笙 (楼主)
    2020-11-21 18:02

    Here's a benchmark for the case when increment operators are in different translation units. Compiler with g++ 4.5.

    Ignore the style issues for now

    // a.cc
    #include 
    #include 
    class Something {
    public:
        Something& operator++();
        Something operator++(int);
    private:
        std::array data;
    };
    
    int main () {
        Something s;
    
        for (int i=0; i<1024*1024*30; ++i) ++s; // warm up
        std::clock_t a = clock();
        for (int i=0; i<1024*1024*30; ++i) ++s;
        a = clock() - a;
    
        for (int i=0; i<1024*1024*30; ++i) s++; // warm up
        std::clock_t b = clock();
        for (int i=0; i<1024*1024*30; ++i) s++;
        b = clock() - b;
    
        std::cout << "a=" << (a/double(CLOCKS_PER_SEC))
                  << ", b=" << (b/double(CLOCKS_PER_SEC)) << '\n';
        return 0;
    }
    

    O(n) increment

    Test

    // b.cc
    #include 
    class Something {
    public:
        Something& operator++();
        Something operator++(int);
    private:
        std::array data;
    };
    
    
    Something& Something::operator++()
    {
        for (auto it=data.begin(), end=data.end(); it!=end; ++it)
            ++*it;
        return *this;
    }
    
    Something Something::operator++(int)
    {
        Something ret = *this;
        ++*this;
        return ret;
    }
    

    Results

    Results (timings are in seconds) with g++ 4.5 on a virtual machine:

    Flags (--std=c++0x)       ++i   i++
    -DPACKET_SIZE=50 -O1      1.70  2.39
    -DPACKET_SIZE=50 -O3      0.59  1.00
    -DPACKET_SIZE=500 -O1    10.51 13.28
    -DPACKET_SIZE=500 -O3     4.28  6.82
    

    O(1) increment

    Test

    Let us now take the following file:

    // c.cc
    #include 
    class Something {
    public:
        Something& operator++();
        Something operator++(int);
    private:
        std::array data;
    };
    
    
    Something& Something::operator++()
    {
        return *this;
    }
    
    Something Something::operator++(int)
    {
        Something ret = *this;
        ++*this;
        return ret;
    }
    

    It does nothing in the incrementation. This simulates the case when incrementation has constant complexity.

    Results

    Results now vary extremely:

    Flags (--std=c++0x)       ++i   i++
    -DPACKET_SIZE=50 -O1      0.05   0.74
    -DPACKET_SIZE=50 -O3      0.08   0.97
    -DPACKET_SIZE=500 -O1     0.05   2.79
    -DPACKET_SIZE=500 -O3     0.08   2.18
    -DPACKET_SIZE=5000 -O3    0.07  21.90
    

    Conclusion

    Performance-wise

    If you do not need the previous value, make it a habit to use pre-increment. Be consistent even with builtin types, you'll get used to it and do not run risk of suffering unecessary performance loss if you ever replace a builtin type with a custom type.

    Semantic-wise

    • i++ says increment i, I am interested in the previous value, though.
    • ++i says increment i, I am interested in the current value or increment i, no interest in the previous value. Again, you'll get used to it, even if you are not right now.

    Knuth.

    Premature optimization is the root of all evil. As is premature pessimization.

提交回复
热议问题