ทั้ง static_cast และ reinterpret_cast ดูเหมือนจะทำงานได้ดีในการคัดเลือกโมฆะ * ไปยังตัวชี้ประเภทอื่น มีเหตุผลที่ดีที่จะสนับสนุนอีกฝ่ายหรือไม่?
ทั้ง static_cast และ reinterpret_cast ดูเหมือนจะทำงานได้ดีในการคัดเลือกโมฆะ * ไปยังตัวชี้ประเภทอื่น มีเหตุผลที่ดีที่จะสนับสนุนอีกฝ่ายหรือไม่?
คำตอบ:
ใช้static_cast
: มันเป็นเพี้ยนที่แคบที่สุดที่อธิบายการแปลงที่ทำที่นี่
มีความเข้าใจผิดว่าการใช้reinterpret_cast
จะเป็นการจับคู่ที่ดีกว่าเพราะมันหมายถึง“ ไม่สนใจความปลอดภัยของประเภทอย่างสมบูรณ์และเพิ่งส่งจาก A ถึง B”
reinterpret_cast
แต่นี้ไม่จริงอธิบายผลของการที่ ค่อนข้างreinterpret_cast
มีความหมายจำนวนมากสำหรับทุกสิ่งที่กล่าวว่า“ การแมปที่ดำเนินการโดยreinterpret_cast
เป็นการนำมาใช้งานที่กำหนดไว้” [5.2.10.3]
แต่ในกรณีเฉพาะของการคัดเลือกจากvoid*
ไปยังT*
การทำแผนที่นั้นถูกกำหนดไว้อย่างสมบูรณ์ตามมาตรฐาน กล่าวคือเพื่อกำหนดประเภทให้กับตัวชี้แบบไม่พิมพ์โดยไม่ต้องเปลี่ยนที่อยู่
static_cast
นี่คือเหตุผลที่จะชอบ
ยิ่งไปกว่านั้นและที่สำคัญกว่านั้นก็คือความจริงที่ว่าการใช้งานทุกครั้งreinterpret_cast
นั้นอันตรายอย่างยิ่งเพราะมันจะแปลงสิ่งใด ๆ ให้เป็นอย่างอื่น (สำหรับตัวชี้) ในขณะที่static_cast
มีข้อ จำกัด มากกว่าดังนั้นจึงเป็นการป้องกันที่ดีกว่า สิ่งนี้ได้ช่วยฉันจากข้อผิดพลาดที่ฉันพยายามบังคับให้ตัวชี้ประเภทหนึ่งไปยังอีกประเภทหนึ่งโดยไม่ตั้งใจ
นี่เป็นคำถามที่ยากมาก ในอีกด้านหนึ่ง Konrad สร้างจุดที่ยอดเยี่ยมเกี่ยวกับข้อกำหนด spec สำหรับreinterpret_castแม้ว่าในทางปฏิบัติมันอาจทำสิ่งเดียวกัน ในทางกลับกันถ้าคุณกำลังชี้ไปที่ประเภทตัวชี้ (ตามปกติเมื่อทำการจัดทำดัชนีในหน่วยความจำผ่านอักขระ * *, static_castจะสร้างข้อผิดพลาดของคอมไพเลอร์และคุณจะถูกบังคับให้ใช้reinterpret_castต่อไป
ในทางปฏิบัติฉันใช้reinterpret_castเพราะเป็นการอธิบายถึงเจตนาของการดำเนินการร่าย คุณสามารถสร้างกรณีให้ผู้ปฏิบัติงานรายอื่นเพื่อระบุตัวชี้ reinterprets เท่านั้น (ซึ่งรับประกันที่อยู่เดียวกันที่ส่งคืน) แต่ไม่มีหนึ่งในมาตรฐาน
reinterpret_cast
!
ฉันแนะนำให้ใช้นักแสดงที่อ่อนแอที่สุดที่เป็นไปได้เสมอ
reinterpret_cast
float
อาจจะใช้ในการส่งตัวชี้ไปยัง ยิ่งการทำลายโครงสร้างมากขึ้นเท่าใดนัก
ในกรณีของchar*
ฉันจะใช้นักแสดง c สไตล์จนกว่าเราจะมีบางอย่างreinterpret_pointer_cast
เพราะมันอ่อนแอและไม่มีอะไรเพียงพอ
float f = *reinterpret_cast<const float*>(&p);
float
ซึ่งเป็นเท็จ บรรยากาศการแสดงออกvoid **
ไปconst float *
แล้วใช้การดำเนินการ dereference (ซึ่งไม่หล่อ) การแปลงไปconst float *
float
ความชอบส่วนบุคคลของฉันขึ้นอยู่กับความรู้เรื่องรหัสเช่นนี้:
void* data = something;
MyClass* foo = reinterpret_cast<MyClass*>(data);
foo->bar();
หรือ
typedef void* hMyClass; //typedef as a handle or reference
hMyClass = something;
const MyClass& foo = static_cast<MyClass&>(*hMyClass);
foo.bar();
พวกเขาทั้งสองทำสิ่งเดียวกันในตอนท้าย แต่ static_cast ดูเหมือนจะเหมาะสมกว่าในแอพชั้นกลาง, สภาพแวดล้อมของแอปในขณะที่การตีความการส่งซ้ำนั้นดูเหมือนว่าสิ่งที่คุณจะเห็นใน IMHO ระดับต่ำกว่าไลบรารี