当将指针投射到对象时,使用或不引用有什么区别?
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);
}发布于 2022-05-22 14:53:01
初步评论
首先,请记住,强制转换void*指针在C++中是一件相当危险的事情,如果指向的对象与您要转换的类型不兼容,这可能是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_,而是一个子类型,那么多态就可以工作,也就是说,如果您调用一个虚拟函数,那么对应于对象的实际运行时类型的那个将被调用。
发布于 2022-05-22 14:51:26
案例1
在此,我们审议以下声明:
SerialNow_ SerialNow = *((SerialNow_*)p);在这里,void* p被转换为SerialNow_* (使用显式类型转换)。接下来,生成的SerialNow_*是使用取消引用的,使用*operator生成一个SerialNow_类型的对象。
最后,生成的SerialNow_对象被用作初始化器,用于初始化左侧名为SerialNow的对象。新初始化的对象SerialNow是原始对象的副本。这意味着,如果您对SerialNow进行更改,它将不会影响p所指向的原始对象。
案例2
在此,我们审议以下声明:
SerialNow_ &SerialNow = *((SerialNow_*)p); 在本例中,大多数进程与案例1相同,但这次SerialNow是结果对象的别名。这与案例1不同,只有在案例1中,左侧的对象SerialNow是原始对象的副本,而左边的SerialNow是对原始对象的lvalue引用。这意味着,如果您对SerialNow进行更改,它将影响p所指向的原始对象。
案例3
在此,我们审议以下声明:
SerialNow_ *SerialNow = ((SerialNow_*)p);在这里,void* p被抛给了SerialNow_*。但结果指针是,与案例1和案例2不同,没有取消引用的。因此,在这里,左手边的名为SerialNow的对象是由显式类型转换产生的指针初始化的。
此外,SerialNow是由显式类型转换产生的指针的副本。
https://stackoverflow.com/questions/72338190
复制相似问题