Search code examples
c++pointerscastingreferencedereference

className SerialNow = *((className*)ptr); vs className &SerialNow = *((className*)ptr);


What is difference between using or not reference when casting pointer to object?

void someClass::method() {
    xTaskCreatePinnedToCore(someTaskHandler,"SerialNowTaskTX",XT_STACK_MIN_SIZE*3,this,4,&taskHandleTX,0); // passing 'this' to task handler
}

void someTaskHandler(void *p) {
    SerialNow_ SerialNow = *((SerialNow_*)p); // compile but not working properly
    SerialNow_ &SerialNow = *((SerialNow_*)p); // compile and working
    SerialNow_ *SerialNow = ((SerialNow_*)p); // compile and working but I prefer . over ->
    int A = SerialNow.somethingA;
    SerialNow.somethingB();

    while(1) {
    
    }

    vTaskDelete(NULL);
}

Solution

  • Preliminary remark

    First, keep in mind that casting void* pointers is in C++ a rather dangerous thing, that can be UB if the object pointed to is not compatible with the type you're casting to.

    Instead of a C-like cast between parenthesis, prefer a C++ more explicit cast, that shows better the level of danger. If p would be a polymorphic base type, prefer using the safer dynamic_cast. Otherwise use a static_cast to avoid some common mistakes. Only in last resort use reinterpret_cast, but you'd have to be really sure about what you're doing.

    What's the difference between your statements?

    If we'd suppose that p is a valid pointer to a type that is compatible with SerialNow_ this is the meaning of your different statements:

    SerialNow_ SerialNow = *((SerialNow_*)p); 
    

    The first makes a copy of the the object that is pointed by p. If you later change the content of the object pointed by b, it will have no impact on the object SerialNow. Keep in mind that if the object pointed by p is not a SerialNow_ but a subclass, slicing might occur.

    SerialNow_ &SerialNow = *((SerialNow_*)p);
    

    The second creates a reference that refers to the object that is pointed by p. You can use SerialNow as if it were an object, but in reality it refers to the same object than the one pointed by p:

    SerialNow_ *SerialNow = ((SerialNow_*)p);
    

    The third creates a pointer to the object that is pointed by p:

    The second and the third respect polymorphism. If the object pointed to by p is not a SerialNow_ but a subtype, polymorphism will work, i.e. if you call a virtual function, the one corresponding to the real run-time type of the object will be invoked.