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

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

将指针转换为对象时使用或不使用引用有什么区别?

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);
}

案例一

这里我们考虑语句:

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

这里 void* p 被转换(使用 explicit type conversion)到 SerialNow_*。接下来,结果 SerialNow_* 取消引用 使用 *operator 导致类型为 SerialNow_ 的对象。

最后,生成的 SerialNow_ 对象用作 初始化器 以初始化左侧名为 SerialNow 的对象。新初始化的对象 SerialNow 是原始对象的副本。这意味着如果您对 SerialNow 进行更改,它不会影响 p.

指向的原始对象

案例二

这里我们考虑语句:

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

在这种情况下,除了这次 SerialNow 是结果对象的 别名 之外,大部分过程与情况 1 相同。这与情况 1 的不同之处仅在于,在情况 1 中,左侧的对象 SerialNow 是原始对象的副本,而此处左侧的 SerialNow 是对对象的左值引用原始对象。这意味着如果您对 SerialNow 进行更改,它将影响 p.

指向的原始对象

案例三

这里我们考虑语句:

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

此处 void* p 被转换为 SerialNow_*。但是与情况 1 和情况 2 不同,结果指针 未取消引用 。因此,此处左侧名为 SerialNow 的对象是根据显式类型产生的指针初始化的转换。

此外,SerialNow 是显式类型转换产生的指针副本..

初步评论

首先,请记住,转换 void* 指针在 C++ 中是一件相当危险的事情,如果指向的对象与您要转换为的类型不兼容,则可能是 UB。

而不是括号之间的 C-like 强制转换,更喜欢 C++ 更明确的强制转换,这样可以更好地显示危险级别。如果 p 是多态基类型,最好使用更安全的 dynamic_cast. Otherwise use a static_cast to avoid some common mistakes. Only in last resort use reinterpret_cast,但您必须真正确定自己在做什么。

你们的说法有什么不同?

如果我们假设 p 是指向与 SerialNow_ 兼容的类型的有效指针,这就是您不同语句的含义:

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

第一个复制p指向的对象。如果以后更改b指向的对象的内容,对对象SerialNow没有影响。请记住,如果 p 指向的对象不是 SerialNow_ 而是子类,则可能会出现 slicing

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

第二个创建引用 p 指向的对象。您可以将 SerialNow 当作一个对象来使用,但实际上它指的是与 p:

指向的对象相同的对象
SerialNow_ *SerialNow = ((SerialNow_*)p);

第三个创建一个指向p指向的对象的指针:

第二个和第三个尊重多态性。如果 p 指向的对象不是 SerialNow_ 而是子类型,多态性将起作用,即如果调用虚函数,将调用与对象的真实 run-time 类型对应的函数。