How expensive is it to dereference a pointer?

后端 未结 6 1541
攒了一身酷
攒了一身酷 2020-12-12 15:07

How expensive is it to perform the dereference operation on a pointer?

I can imagine that the memory transfer is somehow proportional to the object size, but I want

6条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-12 15:46

    It depends on what you do with the dereferenced pointer. A mere dereference operation does nothing in itself. It just gets an lvalue of type T which represents your object, if your pointer is a T*

    struct a {
        int big[42];
    };
    
    void f(a * t) {
        // does nothing. Only interesting for standard or compiler writers.
        // it just binds the lvalue to a reference t1. 
        a & t1 = *t; 
    }
    

    If you actually get the value out of that object denoted by the lvalue returned by the dereference operation, the compiler has to copy the data the object contains. For a simple POD, that is just a mere memcpy:

    a aGlobalA;
    void f(a * t) {
        // gets the value of of the object denoted by *t, copying it into aGlobalA
        aGlobalA = *t; 
    }
    

    My gcc port outputs this code for f:

        sub     $29, $29, 24       ; subtract stack-pointer, creating this frame
        stw     $31, $29, 20       ; save return address
        add     $5, $0, $4         ; copy pointer t into $5 (src)
        add     $4, $0, aGlobalA   ; load address of aGlobalA into $4 (dst)
        add     $6, $0, 168        ; put size (168 bytes) as 3rd argument
        jal     memcpy             ; call memcpy
        ldw     $31, $29, 20       ; restore return address
        add     $29, $29, 24       ; add stack-pointer, destroying this frame
        jr      $31
    

    Optimized machine code would use in-line code instead of a call to memcpy, but that's really just an implementation detail. What is important is, that merely *t isn't executing any code, but accessing the value of that object actually needs to copy it.

    Would we have to do with a type having a user defined copy assignment operator, affairs are more complex:

    struct a {
        int big[42];
        void operator=(a const&) { }
    };
    

    The code for the same function f now looks like:

        sub     $29, $29, 8
        add     $29, $29, 8
        jr      $31
    

    Hah. But it wasn't such a surprise, wasn't it? After all, the compiler is supposed to call our operator=, and if it does nothing, the whole function also does nothing!

    Conclusion

    I think the conclusion we can draw is, it all depends on how the returned value of operator* is used. If we have just a pointer that we dereference, we see above that the code generated largely depends on the circumstances. I haven't showed how it behaves if we dereference a class type having overloaded operator* . But essentially, it's just behaving like we saw with operator=. All measurements were done with -O2, so the compiler properly inlined calls :)

提交回复
热议问题