क्यों (int) x के बजाय static_cast <int> (x) का उपयोग करें?


667

मैंने सुना है कि static_castफ़ंक्शन को सी-स्टाइल या साधारण फ़ंक्शन-स्टाइल कास्टिंग के लिए प्राथमिकता दी जानी चाहिए। क्या ये सच है? क्यों?


36
अपने सम्मान पर आपत्ति जताई, पूछा और जवाब दिया
ग्रीम पेरो

25
मैं असहमत हूं, यह अन्य प्रश्न C ++ में परिचय के बीच के अंतर का वर्णन करने के बारे में था। यह सवाल static_cast की वास्तविक उपयोगिता के बारे में है, जो थोड़ा अलग है।
विंसेंट रॉबर्ट

2
हम निश्चित रूप से दो प्रश्नों को मर्ज कर सकते हैं, लेकिन हमें इस थ्रेड से संरक्षित करने की आवश्यकता होगी सी-स्टाइल कास्टिंग पर फ़ंक्शंस का उपयोग करने का लाभ, जो वर्तमान में केवल एक पंक्ति में दूसरे थ्रेड में वर्णित है, जिसमें कोई वोट नहीं है ।
टॉमी हर्बर्ट

6
यह प्रश्न "बिल्ट-इन" प्रकारों के बारे में है, जैसे इंट, जबकि वह प्रश्न वर्ग प्रकारों के बारे में है। ऐसा लगता है कि एक अलग व्याख्या के लिए एक महत्वपूर्ण पर्याप्त अंतर है।

9
static_cast वास्तव में एक ऑपरेटर है, एक फ़ंक्शन नहीं है।
थॉमसमैक्लोड २५'१३

जवाबों:


633

मुख्य कारण यह है कि क्लासिक सी डाले जिसे हम दोनों के बीच कोई भेद नहीं करते है static_cast<>(), reinterpret_cast<>(), const_cast<>(), और dynamic_cast<>()। ये चार चीजें पूरी तरह से अलग हैं।

A static_cast<>()आमतौर पर सुरक्षित है। भाषा में एक वैध रूपांतरण, या एक उपयुक्त निर्माता है जो इसे संभव बनाता है। जब आप विरासत में किसी वर्ग में जाते हैं, तो यह थोड़ा जोखिम भरा होता है; आपको यह सुनिश्चित करना चाहिए कि वस्तु वास्तव में वह वंशज है जिस पर आप दावा करते हैं कि इसका मतलब भाषा से बाहरी है (जैसे कि ऑब्जेक्ट में झंडा)। एक dynamic_cast<>()के रूप में लंबे समय के रूप परिणाम चेक किया गया है (सूचक) या एक संभावित अपवाद के खाते (संदर्भ) में रखा जाता है सुरक्षित है।

दूसरी ओर A reinterpret_cast<>()(या a const_cast<>()) हमेशा खतरनाक होता है। आप संकलक को बताते हैं: "मुझ पर भरोसा करें: मुझे पता है कि यह ऐसा नहीं दिखता है foo(ऐसा लगता है जैसे कि यह परस्पर नहीं है), लेकिन यह है"।

पहली समस्या यह है कि यह बताना लगभग असंभव है कि कोड के बड़े और फैलाने वाले टुकड़ों को देखने और सभी नियमों को जानने के बिना सी-स्टाइल कास्ट में कौन सा होगा।

आइए मान लेते हैं ये:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

अब, इन दोनों को उसी तरह संकलित किया गया है:

CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
                                     // Safe; as long as we checked
                                     // but harder to read

हालाँकि, आइए इसे लगभग समान कोड देखें:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                  // Same as reinterpret_cast<>
                                                  // and it's wrong!!!

जैसा कि आप देख सकते हैं, इसमें शामिल सभी वर्गों के बारे में बहुत कुछ जाने बिना दो स्थितियों के बीच अंतर करने का कोई आसान तरीका नहीं है।

दूसरी समस्या यह है कि सी-स्टाइल कास्ट का पता लगाना बहुत मुश्किल है। जटिल अभिव्यक्तियों में सी-स्टाइल कास्ट को देखना बहुत कठिन हो सकता है। एक पूर्ण उपकरण को लिखना लगभग असंभव है जिसे सी-स्टाइल कास्ट (उदाहरण के लिए एक खोज उपकरण) का पता लगाने की आवश्यकता है, बिना पूर्ण उड़ा सी ++ संकलक फ्रंट-एंड के। दूसरी ओर, "static_cast <" या "reinterpret_cast <" के लिए खोज करना आसान है।

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
      // No compiler error.
      // but the presence of a reinterpret_cast<> is 
      // like a Siren with Red Flashing Lights in your code.
      // The mere typing of it should cause you to feel VERY uncomfortable.

इसका मतलब है कि, न केवल सी-शैली की जातियां अधिक खतरनाक हैं, बल्कि उन सभी को खोजने के लिए यह सुनिश्चित करना बहुत कठिन है कि वे सही हैं।


30
आपको static_castएक वंशानुगत पदानुक्रम नीचे कास्टिंग के लिए उपयोग नहीं करना चाहिए , बल्कि dynamic_cast। कि या तो अशक्त सूचक या एक वैध सूचक लौटेगा।
डेविड थॉर्नले

41
@ डेविड थॉर्नले: मैं सहमत हूं, आमतौर पर। मुझे लगता है कि मैंने static_castउस स्थिति में उपयोग करने के लिए चेतावनी दी । dynamic_castसुरक्षित हो सकता है, लेकिन यह हमेशा सबसे अच्छा विकल्प नहीं है। कभी-कभी आप जानते हैं कि एक सूचक किसी दिए गए उपप्रकार की ओर इशारा करता है, इसका मतलब संकलक से अपारदर्शी है, और एक static_castतेजी से है। कम से कम कुछ वातावरणों में, dynamic_castवैकल्पिक संकलक समर्थन और रनटाइम लागत (आरटीटीआई को सक्षम करना) की आवश्यकता होती है, और आप इसे केवल कुछ चेकों के लिए सक्षम नहीं करना चाहते हैं जो आप स्वयं कर सकते हैं। C ++ की RTTI समस्या का केवल एक संभावित समाधान है।
यूरो मिकेलि

18
C जातियों के बारे में आपका दावा गलत है। सभी C जाती मूल्य रूपांतरण हैं, लगभग C ++ की तुलना में static_cast। C का समतुल्य reinterpret_castहै *(destination_type *)&, अर्थात वस्तु का पता लेना, उस पते को एक अलग प्रकार के लिए सूचक को कास्टिंग करना, और फिर dereferencing। चरित्र प्रकार या कुछ विशेष प्रकार के मामले को छोड़कर, जिसके लिए C इस निर्माण के व्यवहार को परिभाषित करता है, यह आम तौर पर C.
R ..

11
आपका ठीक उत्तर पोस्ट के शरीर को संबोधित करता है। मैं "क्यों (int) x" के स्थान पर static_cast <int> (x) का उपयोग करता हूं शीर्षक के उत्तर की तलाश में था। यह है, प्रकार के लिए int(और intअकेले), का उपयोग क्यों static_cast<int>बनाम के (int)रूप में एकमात्र लाभ वर्ग चर और संकेत के साथ लगता है। निवेदन है कि आप इस बारे में विस्तार से बताएं।
चक्स - मोनिका

31
@chux, int dynamic_castलागू नहीं होता है, लेकिन अन्य सभी कारण खड़े होते हैं। उदाहरण के लिए: मान लीजिए vकि एक फंक्शन पैरामीटर घोषित किया गया है float, फिर (int)vहै static_cast<int>(v)। लेकिन अगर आप पैरामीटर को बदलते हैं float*, तो (int)vचुपचाप हो जाता है reinterpret_cast<int>(v)जबकि static_cast<int>(v)अवैध और सही ढंग से कंपाइलर द्वारा पकड़ा जाता है।
यूरो मिसेल

115

एक व्यावहारिक टिप: यदि आप प्रोजेक्ट को व्यवस्थित करने की योजना बनाते हैं, तो आप अपने स्रोत कोड में static_cast कीवर्ड के लिए आसानी से खोज सकते हैं।


3
आप भले ही "(int)" जैसे कोष्ठक का उपयोग करके खोज कर सकते हैं, लेकिन C ++ शैली की कास्टिंग का उपयोग करने के लिए अच्छा उत्तर और वैध कारण।
माइक

4
@ माइक जो गलत सकारात्मकता पाएंगे - एक एकल intपैरामीटर के साथ एक फ़ंक्शन घोषणा ।
नाथन उस्मान

1
यह गलत संकेत दे सकता है: यदि आप एक ऐसा कोडबेस खोज रहे हैं, जहां आप एकमात्र लेखक नहीं हैं, तो आपको सी-स्टाइल कास्ट नहीं मिलेंगे, दूसरों ने कुछ कारणों से पेश किया होगा।
रुस्लान

7
इस परियोजना को सुव्यवस्थित करने के लिए यह कैसे मदद करेगा?
बिल्लो

आप static_cast के लिए खोज नहीं करेंगे, क्योंकि यह सबसे सही होने की संभावना है। आप static_cast को फ़िल्टर करना चाहते हैं, जबकि आप reinterpret_cast, const_cast, और शायद dynam_cast की खोज करते हैं, क्योंकि वे उन स्थानों को इंगित करते हैं जिन्हें फिर से डिज़ाइन किया जा सकता है। सी-कास्ट सभी को एक साथ मिलाता है और आपको कास्टिंग का कारण नहीं देता है।
खींचन

78

संक्षेप में :

  1. static_cast<>() आपको एक संकलित समय की जाँच करने की क्षमता देता है, सी-स्टाइल कास्ट नहीं करता है।
  2. static_cast<>()C ++ स्रोत कोड के अंदर कहीं भी आसानी से देखा जा सकता है; इसके विपरीत, C_Style कास्ट स्पॉट करना कठिन है।
  3. इरादों को C ++ जातियों का उपयोग करके बेहतर ढंग से व्यक्त किया जाता है।

अधिक स्पष्टीकरण :

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

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

चूंकि यह 4-बाइट पॉइंटर में आवंटित मेमोरी के 1 बाइट की ओर इशारा करता है, इसलिए इस पॉइंटर पर लिखने से या तो रन-टाइम त्रुटि होगी या कुछ आसन्न मेमोरी को अधिलेखित कर देगा।

*p = 5; // run-time error: stack corruption

सी-स्टाइल कास्ट के विपरीत, स्टेटिक कास्ट कंपाइलर को यह जांचने की अनुमति देगा कि पॉइंटर और पॉइंटी डेटा प्रकार संगत हैं, जो प्रोग्रामर को संकलन के दौरान इस गलत पॉइंटर असाइनमेंट को पकड़ने की अनुमति देता है।

int *q = static_cast<int*>(&c); // compile-time error

आगे पढ़ें:
static_cast <> और C स्टाइल कास्टिंग
और रेगुलर कास्ट बनाम static_cast बनाम डायनामिक_कास्ट में क्या अंतर है


21
मैं असहमत हूं कि static_cast<>()अधिक पठनीय है। मेरा मतलब है, कभी-कभी यह होता है, लेकिन ज्यादातर समय - विशेष रूप से मूल पूर्णांक प्रकारों पर - यह सिर्फ बुरी तरह से और अनावश्यक रूप से क्रिया है। उदाहरण के लिए: यह एक फ़ंक्शन है जो 32-बिट शब्द के बाइट्स को स्वैप करता है। static_cast<uint##>()जातियों का उपयोग करना पढ़ना लगभग असंभव होगा , लेकिन जातियों का उपयोग करना समझना काफी आसान है (uint##)कोड की तस्वीर: imgur.com/NoHbGve
टोड लेहमैन

3
@ToddLehman: धन्यवाद, लेकिन मैंने alwaysया तो नहीं कहा । (लेकिन अधिकांश बार हाँ) ऐसे मामले हैं जहां सी शैली डाली अधिक पठनीय है। C शैली कास्टिंग के कारणों में से एक है कि अभी भी रहते हैं और c ++ imho में किकिंग करते हैं। :) वैसे यह एक बहुत अच्छा उदाहरण था
रीका

8
उस छवि में @ToddLehman कोड (uint32_t)(uint8_t)उन बाइट्स को प्राप्त करने के लिए जंजीर ( ) को प्राप्त करने के लिए दो कास्ट का उपयोग करता है इसके अलावा सबसे कम रीसेट किए जाते हैं। उसके लिए बिटवाइस और ( 0xFF &) है। जातियों का उपयोग इरादे को बाधित कर रहा है।
02ö तिइब

28

सवाल सिर्फ स्टैटर static_cast या C स्टाइल कास्टिंग का उपयोग करने से बड़ा है क्योंकि C स्टाइल कास्ट का उपयोग करते समय अलग-अलग चीजें होती हैं। C ++ कास्टिंग ऑपरेटर्स का उद्देश्य इन ऑपरेशनों को अधिक स्पष्ट करना है।

सतह पर static_cast और C शैली की कास्ट एक ही चीज़ के लिए दिखाई देते हैं, उदाहरण के लिए जब एक मान को दूसरे में रखते हैं:

int i;
double d = (double)i;                  //C-style cast
double d2 = static_cast<double>( i );  //C++ cast

इन दोनों ने पूर्णांक मान को दोगुना कर दिया। हालाँकि जब पॉइंटर्स के साथ काम किया जाता है तो चीजें अधिक जटिल हो जाती हैं। कुछ उदाहरण:

class A {};
class B : public A {};

A* a = new B;
B* b = (B*)a;                                  //(1) what is this supposed to do?

char* c = (char*)new int( 5 );                 //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error

इस उदाहरण में (1) शायद ठीक है क्योंकि ए द्वारा बताई गई वस्तु वास्तव में बी का उदाहरण है लेकिन क्या होगा यदि आप उस बिंदु पर कोड में नहीं जानते हैं कि वास्तव में क्या इंगित करता है? (2) शायद पूरी तरह से कानूनी (आप केवल पूर्णांक के एक बाइट को देखना चाहते हैं), लेकिन यह भी एक गलती हो सकती है जिस स्थिति में एक त्रुटि अच्छी होगी, जैसे (3)। C ++ कास्टिंग ऑपरेटर्स का उद्देश्य है कि जब संभव हो संकलन-समय या रन-टाइम त्रुटियों को प्रदान करके इन मुद्दों को कोड में उजागर किया जाए।

तो, सख्त "मूल्य कास्टिंग" के लिए आप static_cast का उपयोग कर सकते हैं। यदि आप चाहते हैं कि रन-टाइम पॉलीमोर्फिक कास्टिंग पॉइंटर्स डायनामिक_कास्ट का उपयोग करें। यदि आप वास्तव में प्रकारों के बारे में भूलना चाहते हैं, तो आप reintrepret_cast का उपयोग कर सकते हैं। और बस खिड़की से बाहर फेंक वहाँ const_cast है।

वे कोड को अधिक स्पष्ट करते हैं ताकि यह ऐसा लगे जैसे आप जानते हैं कि आप क्या कर रहे थे।


26

static_castइसका मतलब है कि आप गलती से const_castया reinterpret_cast, जो कि एक अच्छी बात नहीं है।


4
सी स्टाइल कास्ट पर अतिरिक्त (हालांकि मामूली) लाभ यह है कि यह अधिक खड़ा होता है (कुछ बुरा कर रहा है, बदसूरत दिखना चाहिए) और यह अधिक grep-सक्षम है।
माइकल बुरु

4
मेरी किताब में grep- क्षमता हमेशा एक प्लस है।
Branan

7
  1. अनुमति देता है कि grep या इसी तरह के औजारों का उपयोग करके जातियां आपके कोड में आसानी से मिल सकती हैं।
  2. यह स्पष्ट करता है कि आप किस प्रकार का कास्ट कर रहे हैं, और इसे लागू करने में कंपाइलर की मदद को उलझा रहे हैं। यदि आप केवल कॉन्स्ट-नेस को दूर करना चाहते हैं, तो आप const_cast का उपयोग कर सकते हैं, जो आपको अन्य प्रकार के रूपांतरण करने की अनुमति नहीं देगा।
  3. जातियां स्वाभाविक रूप से बदसूरत हैं - आप एक प्रोग्रामर के रूप में यह तय कर रहे हैं कि संकलक आपके कोड को कैसे व्यवहार करेगा। आप संकलक से कह रहे हैं, "मैं आपसे बेहतर जानता हूं।" यह मामला होने के नाते, यह समझ में आता है कि कलाकारों का प्रदर्शन करने के लिए एक मामूली दर्दनाक चीज होनी चाहिए, और यह कि उन्हें आपके कोड में रहना चाहिए, क्योंकि वे समस्याओं का एक संभावित स्रोत हैं।

प्रभावी C ++ परिचय देखें


मैं पूरी तरह से कक्षाओं के लिए इससे सहमत हूं लेकिन क्या POD प्रकारों के लिए C ++ स्टाइल कास्ट का उपयोग करने से कोई मतलब है?
ज़ाचरी क्रूस २

मुझे ऐसा लगता है। सभी 3 कारण PODs पर लागू होते हैं, और वर्गों और PODs के लिए अलग-अलग होने के बजाय यह केवल एक नियम के लिए उपयोगी है।
JohnMcG

दिलचस्प है, मुझे संशोधित करना पड़ सकता है कि मैं पीओडी प्रकारों के लिए भविष्य के कोड में कैसे अपनी कास्ट करता हूं।
जकरी क्रस

7

यह इस बारे में है कि आप कितने प्रकार की सुरक्षा थोपना चाहते हैं।

जब आप लिखते हैं (bar) foo(जो कि reinterpret_cast<bar> fooयदि आपने एक प्रकार का रूपांतरण ऑपरेटर प्रदान नहीं किया है तो बराबर है ) आप कंपाइलर को सुरक्षा की अनदेखी करने के लिए कह रहे हैं, और जैसा बताया गया है वैसा ही करें।

जब आप लिखते हैं static_cast<bar> fooतो आप संकलक से कम से कम यह जांचने के लिए पूछ रहे हैं कि प्रकार रूपांतरण कुछ अर्थ कोड को सम्मिलित करने के लिए अभिन्न प्रकार के लिए समझ में आता है।


EDIT 2014-02-26

मैंने यह उत्तर 5 साल पहले लिखा था, और मुझे यह गलत लगा। (टिप्पणियाँ देखें।) लेकिन यह अभी भी बढ़ जाता है!


8
(bar) foo, reinterpret_cast <bar> (foo) के बराबर नहीं है। "(TYPE) एक्सप" के नियम यह हैं कि यह उपयोग करने के लिए उपयुक्त C ++ स्टाइल कास्ट का चयन करेगा, जिसमें रीइंटरप्रिटेशन कास्ट शामिल हो सकता है।
रिचर्ड कॉर्डन

अच्छी बात। इस सवाल का निश्चित जवाब यूरो माइकेल ने दिया।
पितरौ

1
इसके अलावा, यह static_cast<bar>(foo)कोष्ठक के साथ है। उसी के लिए reinterpret_cast<bar>(foo)
LF

6

C स्टाइल कास्ट कोड के एक ब्लॉक में याद करना आसान है। सी ++ स्टाइल कास्ट न केवल बेहतर अभ्यास है; वे लचीलेपन का अधिक से अधिक डिग्री प्रदान करते हैं।

reinterpret_cast सूचक प्रकार के रूपांतरणों के लिए अभिन्न अनुमति देता है, हालांकि यदि दुरुपयोग किया जाता है तो असुरक्षित हो सकता है।

static_cast सांख्यिक प्रकारों के लिए अच्छा रूपांतरण प्रदान करता है, जैसे कि enums से ints या ints से फ़्लोट्स या किसी भी प्रकार के डेटा पर, जो आपके प्रकार के बारे में आश्वस्त हैं। यह कोई रन टाइम चेक नहीं करता है।

दूसरी ओर डायनेमिक_कास्ट किसी भी अस्पष्ट असाइनमेंट या रूपांतरण को चिह्नित करने वाले इन चेक को करेगा। यह केवल पॉइंटर्स और रेफरेंस पर काम करता है और एक ओवरहेड को इम्प्रेस करता है।

दूसरों के एक जोड़े हैं, लेकिन ये मुख्य हैं जो आप भर में आएंगे।


4

स्थिर_कास्ट, अलग-अलग बिंदुओं से लेकर कक्षाओं तक, का उपयोग कक्षाओं में स्पष्ट रूप से परिभाषित रूपांतरणों को करने के लिए, साथ ही साथ मूलभूत प्रकारों के बीच मानक रूपांतरण करने के लिए भी किया जा सकता है:

double d = 3.14159265;
int    i = static_cast<int>(d);

4
कोई भी क्यों लिखेगा static_cast<int>(d), हालांकि, (int)dइतना अधिक संक्षिप्त और पठनीय है? (मैं मूल प्रकार के मामले में हूं, वस्तु सूचक नहीं।)
टॉड लेहमैन

@ gd1 - कोई भी पठनीयता से ऊपर क्यों रखेगा? (वास्तव में आधा गंभीर)
टोड लेहमैन

2
@ToddLehman: मुझे, कुछ विशेष प्रकारों के लिए एक अपवाद बनाने पर विचार सिर्फ इसलिए कि वे किसी भी तरह से आपके लिए विशेष हैं, इससे मुझे कोई मतलब नहीं है, और मैं आपकी पठनीयता की बहुत धारणा पर असहमत हूं। शॉर्टर का मतलब अधिक पठनीय नहीं है, जैसा कि मैंने उस छवि से देखा है जिसे आपने किसी अन्य टिप्पणी में पोस्ट किया है।
जीडी

2
static_cast एक विशेष प्रकार का रूपांतरण करने के लिए एक स्पष्ट और सचेत निर्णय है। इसलिए यह इरादे की स्पष्टता को जोड़ता है। कोड समीक्षा, बग या अपग्रेड एक्सरसाइज में रूपांतरण के लिए स्रोत फ़ाइलों को खोजने के लिए एक मार्कर के रूप में भी यह बहुत आसान है।
Persixty

1
@ToddLehman काउंटरपॉइंट: इतना अधिक पठनीय (int)dहोने पर कोई क्यों लिखेगा int{d}? कंस्ट्रक्टर, या फंक्शन की तरह यदि आपके पास है (), तो सिंटैक्स जटिल अभिव्यक्तियों में कोष्ठक के बुरे सपने में विचलित करने के लिए लगभग इतना तेज़ नहीं है। इस मामले में, यह int i{d}इसके बजाय होगा int i = (int)d। बेहतर आईएमओ है। उस ने कहा, जब मुझे बस एक अभिव्यक्ति में एक अस्थायी की आवश्यकता होती है, तो मैं static_castनिर्माण करता हूं और कभी भी निर्माण कलाकारों का उपयोग नहीं किया है, मुझे नहीं लगता। मैं केवल (C)castsतब उपयोग करता हूं जब जल्दी से डिबग coutएस लिख रहा हूं ...
अंडरस्कोर_ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.