i++ less efficient than ++i, how to show this?

前端 未结 9 1745
暖寄归人
暖寄归人 2020-12-03 14:30

I am trying to show by example that the prefix increment is more efficient than the postfix increment.

In theory this makes sense: i++ needs to be able to return the

相关标签:
9条回答
  • 2020-12-03 15:04

    I like to follow the rule of "say what you mean".

    ++i simply increments. i++ increments and has a special, non-intuitive result of evaluation. I only use i++ if I explicitly want that behavior, and use ++i in all other cases. If you follow this practice, when you do see i++ in code, it's obvious that post-increment behavior really was intended.

    0 讨论(0)
  • 2020-12-03 15:07

    Several points:

    • First, you're unlikely to see a major performance difference in any way
    • Second, your benchmarking is useless if you have optimizations disabled. What we want to know is if this change gives us more or less efficient code, which means that we have to use it with the most efficient code the compiler is able to produce. We don't care whether it is faster in unoptimized builds, we need to know if it is faster in optimized ones.
    • For built-in datatypes like integers, the compiler is generally able to optimize the difference away. The problem mainly occurs for more complex types with overloaded increment iterators, where the compiler can't trivially see that the two operations would be equivalent in the context.
    • You should use the code that clearest expresses your intent. Do you want to "add one to the value", or "add one to the value, but keep working on the original value a bit longer"? Usually, the former is the case, and then a pre-increment better expresses your intent.

    If you want to show the difference, the simplest option is simply to impement both operators, and point out that one requires an extra copy, the other does not.

    0 讨论(0)
  • 2020-12-03 15:08

    In the general case, the post increment will result in a copy where a pre-increment will not. Of course this will be optimized away in a large number of cases and in the cases where it isn't the copy operation will be negligible (ie., for built in types).

    Here's a small example that show the potential inefficiency of post-increment.

    #include <stdio.h>
    
    class foo 
    {
    
    public:
        int x;
    
        foo() : x(0) { 
            printf( "construct foo()\n"); 
        };
    
        foo( foo const& other) { 
            printf( "copy foo()\n"); 
            x = other.x; 
        };
    
        foo& operator=( foo const& rhs) { 
            printf( "assign foo()\n"); 
            x = rhs.x;
            return *this; 
        };
    
        foo& operator++() { 
            printf( "preincrement foo\n"); 
            ++x; 
            return *this; 
        };
    
        foo operator++( int) { 
            printf( "postincrement foo\n"); 
            foo temp( *this);
            ++x;
            return temp; 
        };
    
    };
    
    
    int main()
    {
        foo bar;
    
        printf( "\n" "preinc example: \n");
        ++bar;
    
        printf( "\n" "postinc example: \n");
        bar++;
    }
    

    The results from an optimized build (which actually removes a second copy operation in the post-increment case due to RVO):

    construct foo()
    
    preinc example: 
    preincrement foo
    
    postinc example: 
    postincrement foo
    copy foo()
    

    In general, if you don't need the semantics of the post-increment, why take the chance that an unnecessary copy will occur?

    Of course, it's good to keep in mind that a custom operator++() - either the pre or post variant - is free to return whatever it wants (or even do whatever it wants), and I'd imagine that there are quite a few that don't follow the usual rules. Occasionally I've come across implementations that return "void", which makes the usual semantic difference go away.

    0 讨论(0)
提交回复
热议问题