क्या मुझे जो कुछ भी शून्य है * कास्टिंग करते समय static_cast या reinterpret_cast का उपयोग करना चाहिए


202

Static_cast और reinterpret_cast दोनों ही एक अन्य पॉइंटर टाइप * शून्य की कास्टिंग के लिए ठीक काम करते हैं। क्या एक दूसरे पर एहसान करने का एक अच्छा कारण है?


78
@anon जाहिर है कि आपने इससे पहले कभी POSIX थ्रेड्स के साथ काम नहीं किया है।
user470379

7
@ user470379 वाह ... यही कारण है कि मैं SO पर इस सवाल पर उतरा! बहुत बढ़िया अवलोकन :-)।
Ogre Psalm33

जवाबों:


148

उपयोग करेंstatic_cast : यह सबसे संकीर्ण कास्ट है जो वास्तव में वर्णन करता है कि यहां क्या रूपांतरण किया गया है।

एक गलत धारणा है कि इसका उपयोग reinterpret_castएक बेहतर मैच होगा क्योंकि इसका मतलब है "पूरी तरह से सुरक्षा को अनदेखा करना और ए से बी तक कास्ट करना"।

हालांकि, यह वास्तव में एक के प्रभाव का वर्णन नहीं करता है reinterpret_cast। बल्कि, इसके reinterpret_castकई अर्थ हैं, जिनमें से सभी के लिए यह है कि "द्वारा निष्पादित मानचित्रण reinterpret_castकार्यान्वयन-परिभाषित है।" [5.2.10.3]

लेकिन से कास्टिंग के विशेष मामले में void*करने के लिए T*मानचित्रण पूरी तरह से मानक से अच्छी तरह से परिभाषित है, अर्थात्, अपने पते को बदले बिना एक टाइप्ड पॉइंटर को टाइप करने के लिए।

यह पसंद करने का एक कारण है static_cast

इसके अतिरिक्त, और यकीनन अधिक महत्वपूर्ण है, यह तथ्य यह है कि इसका हर उपयोग reinterpret_castसर्वथा खतरनाक है क्योंकि यह किसी भी चीज़ को वास्तव में (बिंदुओं के लिए) में परिवर्तित करता है, जबकि static_castयह अधिक प्रतिबंधात्मक है, इस प्रकार यह एक बेहतर स्तर की सुरक्षा प्रदान करता है। इससे मुझे पहले ही बग से बचाया जा चुका है जहां मैंने गलती से एक पॉइंटर टाइप को दूसरे में डालने की कोशिश की थी।


8

यह एक मुश्किल सवाल है। एक ओर, कोनराड पुन: व्याख्या_कास्ट के लिए विशिष्ट परिभाषा के बारे में एक उत्कृष्ट बिंदु बनाता है , हालांकि व्यवहार में यह संभवतः एक ही बात करता है। दूसरी ओर, यदि आप पॉइंटर प्रकारों के बीच कास्टिंग कर रहे हैं (जैसा कि एक चार के माध्यम से मेमोरी में अनुक्रमित करते समय काफी सामान्य है), उदाहरण के लिए, static_cast एक संकलक त्रुटि उत्पन्न करेगा और आपको वैसे भी reinterpret_cast का उपयोग करने के लिए मजबूर किया जाएगा ।

व्यवहार में मैं पुनर्व्याख्या_का उपयोग करता हूं क्योंकि यह कास्ट ऑपरेशन के इरादे के बारे में अधिक वर्णनात्मक है। आप निश्चित रूप से एक अलग ऑपरेटर के लिए पॉइंटर रीइंटरपॉइंट करने के लिए केवल एक केस बना सकते हैं (जो उसी पते की गारंटी देता है), लेकिन मानक में कोई नहीं है।


6
" सूचक को अलग करने के लिए अलग-अलग ऑपरेटर केवल (जो एक ही पते की गारंटी देता है) को पुन: स्थापित करता है " हग? वह ऑपरेटर है reinterpret_cast !
जिज्ञासु

2
@ मानक के अनुसार सही नहीं है। reinterpret_cast गारंटी नहीं देता कि एक ही पते का उपयोग किया जाता है। केवल इतना है कि यदि आप एक प्रकार से दूसरे प्रकार में पुन: व्याख्या करते हैं और फिर से वापस आते हैं , तो आपको वही पता वापस मिलेगा जो आपने शुरू किया था।
क्लाइडइजहॉस्ट

0

मैं हमेशा सबसे कमजोर संभव कलाकारों का उपयोग करने का सुझाव देता हूं।

reinterpret_castएक करने के लिए एक सूचक डालने के लिए इस्तेमाल किया जा सकता है float। कलाकारों को जितना अधिक संरचना-तोड़ना होता है, उसका उपयोग करने के लिए उतना ही अधिक ध्यान देने की आवश्यकता होती है।

के मामले में char*, मैं सी-स्टाइल कास्ट का उपयोग करूंगा, जब तक कि हमारे पास कुछ न हो reinterpret_pointer_cast, क्योंकि यह कमजोर है और कुछ भी पर्याप्त नहीं है।


2
" reinterpret_cast का उपयोग एक फ्लोट को पॉइंटर डालने के लिए किया जा सकता है। " निश्चित रूप से नहीं!
जिज्ञासु

3
संभवतयाfloat f = *reinterpret_cast<const float*>(&p);
बेन वोइगट

2
@BenVoigt यह संकेत के बीच कास्टिंग है; उनमें से एक फ्लोट पॉइंटर हुआ।
नोडकई

5
@BenVoigt "संपूर्ण अभिव्यक्ति" हालांकि एक कलाकार नहीं है। अभिव्यक्ति में एक कलाकारों के लिए लागू होने वाला एक डीरेंस होता है। आपने दावा किया कि एक पॉइंटर का उपयोग करना संभव था float, जो कि गलत है। अभिव्यक्ति को बदलने के लिए जाती void **है const float *, और फिर एक dereference ऑपरेशन (जो एक कास्ट नहीं है) का उपयोग करता है, को बदलने के const float *लिए float
एमएम

2
@BenVoigt ने किसी को "मैं कैसे डालूं ..." पूछने के जवाब में उस कोड की पेशकश की, और फिर जब किसी ने कहा कि कोड पॉइंटर्स (जो यह करता है) के बीच कास्ट करता है, तो आपने कहा "नोप"
MM

-7

मेरी व्यक्तिगत प्राथमिकता इस तरह कोड साक्षरता पर आधारित है:

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 में देखेंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.