当将指针转换为对象时,使用或不使用引用有什么区别?
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);
}
备注
首先,请记住,在c++中强制转换void*
指针是一件相当危险的事情,如果指向的对象与您要强制转换的类型不兼容,则可能是UB。
与其在括号之间进行类似C的强制转换,不如使用c++的更显式强制转换,这样可以更好地显示危险级别。如果p是多态碱基类型,建议使用更安全的dynamic_cast
。否则,请使用static_cast
,以避免一些常见错误。只有在最后关头才使用reinterpret_cast
,但是你必须非常确定你在做什么。
你们的陈述有什么不同?
如果我们假设p是一个有效的指针,指向与SerialNow_
兼容的类型,这就是你的不同语句的含义:
SerialNow_ SerialNow = *((SerialNow_*)p);
第一个对p所指向的对象进行复制。如果稍后更改b所指向的对象的内容,则不会对对象SerialNow
产生影响。请记住,如果p所指向的对象不是SerialNow_
,而是一个子类,则可能发生切片。
SerialNow_ &SerialNow = *((SerialNow_*)p);
第二个参数创建了一个引用,该引用指向p所指向的对象。您可以将SerialNow
当作对象来使用,但实际上它指向的对象与p所指向的对象是同一个对象:
SerialNow_ *SerialNow = ((SerialNow_*)p);
第三个语句创建一个指向p所指向的对象的指针:
第二和第三方面的多态性。如果p所指向的对象不是SerialNow_
,而是一个子类型,则多态性将工作,即如果调用虚函数,将调用与该对象的实际运行时类型相对应的对象。
Case 1
这里我们考虑语句:
SerialNow_ SerialNow = *((SerialNow_*)p);
这里void*
p
被强制转换(使用显式类型转换)为SerialNow_*
。接下来,生成的SerialNow_*
是解引用的使用*operator
生成SerialNow_
类型的对象。
SerialNow_
对象被用作初始化式初始化左侧名为SerialNow
的对象。新初始化的对象SerialNow
是原始对象的副本。这意味着如果你改变了SerialNow
,它不会影响p
所指向的原始对象。
案例2
这里我们考虑语句:
SerialNow_ &SerialNow = *((SerialNow_*)p);
在这种情况下,除了SerialNow
是别名之外,大部分过程与情况1相同。对于结果对象。这与情形一的唯一不同之处在于,在情形1中,左侧的对象SerialNow
是原始对象的副本,而这里左侧的SerialNow
是对原始对象的左值引用。这意味着如果你改变了SerialNow
,它将影响p
指向的原始对象。
情况3
这里我们考虑语句:
SerialNow_ *SerialNow = ((SerialNow_*)p);
这里void*
p
被强制转换为SerialNow_*
。但是结果指针是未被解引用的不像情形1和情形2。因此,这里左侧名为SerialNow
的对象是通过显式类型转换产生的指针初始化的。
而且,SerialNow
是由显式类型转换产生的指针的副本。