2015-10-08 5 views
5

स्कॉट मेयर की किताब प्रभावी आधुनिक C++ में हम, पढ़ सकते हैं कि:ऑटो और static_casts - अच्छा अभ्यास

std::vector<bool> features(const Widget& w); 
Widget w; 
… 
bool highPriority = features(w)[5]; 
… 
processWidget(w, highPriority); 

और ऑटो के साथ एक विकल्प

auto highPriority = features(w)[5]; 

जो वजह से, अपरिभाषित व्यवहार का कारण बनता है तथ्य यह है कि features()std::vector<bool> लौटा रहा है, जो opearator[] से मान लौटाते समय प्रॉक्सी ऑब्जेक्ट प्रकार std::vector<bool>::reference का उपयोग करता है।

इस समाधान के लिए auto का उपयोग न करने की सलाह दी जाती है, लेकिन static_casts का उपयोग करना बंद नहीं किया जाता है।

तो स्कॉट Meyers सलाह उपयोग करने के लिए:

auto highPriority = static_cast<bool>(features(w)[5]); 

के बजाय:

bool highPriority = features(w)[5]; 

मेरा प्रश्न है: उन दोनों के बीच कोई वास्तविक अंतर क्या है? मेरी राय में दोनों एक जैसे हैं, क्योंकि दोनों विधियां बिल्कुल वैसे ही कड़ी मेहनत कर रही हैं (फ़ंक्शन फीचर्स में रिटर्न वैल्यू टाइप बदलना चरम उच्च प्राथमिकता को एक अलग प्रकार नहीं बनाता है) और दूसरा लिखने के लिए छोटा है।

+1

बस एक संदेह है, लेकिन मेरे सिर के ऊपर से मैं एक कार्यात्मक अंतर के बारे में नहीं सोच सकता, और स्कॉट का एकमात्र कारण स्थिरता हो सकता है - क्या उसने उसी पुस्तक में कहीं भी व्यावहारिक सब कुछ के लिए 'ऑटो x = 'का उपयोग करने की वकालत नहीं की है ...? (या शायद यह कुछ ऑनलाइन आलेख मैंने देखा था ...) –

+3

@ टोनीड हाँ, स्थिरता शायद कारण है। वह सुझाव देता है कि "आइटम 5 – TartanLlama

+1

में स्पष्ट प्रकार की घोषणाओं को" ऑटो 'पसंद करें "मैं कहूंगा कि पहला समाधान स्पष्ट रूप से पाठक को बताता है" यह बात एक बूल नहीं है, लेकिन मैं इसे एक बूल बनना चाहता हूं "। दूसरा समाधान आमतौर पर पाठक को बताता है "यह एक बूल है या कम से कम इस तरह इस्तेमाल किया जा सकता है" लेकिन समस्या यह है कि अधिकांश पाठक इसे "एक बूल" के रूप में पढ़ते हैं और शायद "हे, अब हमारे पास 'ऑटो' है, इसलिए हम इसे 'ऑटो उच्च प्राथमिकता = विशेषताएं (डब्ल्यू) [5];'! ", और बूम लिखते हैं। यहां तक ​​कि यदि दोनों समाधान तकनीकी रूप से समान हैं, तो पाठक को पहले चेतावनी दी जाती है कि 'सुविधाओं (डब्ल्यू) [5]' का उपयोग करने में कोई समस्या हो सकती है। वैसे, वही समस्या अभिव्यक्ति टेम्पलेट्स जैसी चीजों के साथ होती है। – leemes

उत्तर

7

आप features के इंटरफेस पसंद नहीं है, तो आप एक सहायक समारोह में कुरूपता को छुपा सकते हैं

bool is_high_priority(const Widget& w) 
{ return features(w)[5]; } 

और अब उम्मीद के रूप में अपने

auto highPriority = is_high_priority(w); 

काम करता है।

+0

क्या आप मुझे बता सकते हैं कि कहां है !! से आ रही? क्या यह कुछ नया ऑपरेटर या कुछ है? क्या यह एक कंपाइलर विशिष्ट सुविधा है? मैं किसी भी तरह इसे कहीं भी नहीं ढूंढ सकता – DawidPi

+0

यह पंक्ति में केवल दो नकारात्मक है। '! x'' x' को 'बूल' में बदल देगा (इसे 0 के विरुद्ध तुलना करके), लेकिन विपरीत मान के साथ। '!! x' फिर से'! x' के मान को उलटा कर देगा, शून्य के लिए 'झूठा' और गैर-शून्य के लिए 'सत्य' का उत्पादन करेगा। –

5
features एक समारोह है कि एक std::vector<bool> रिटर्न के साथ

,

auto highPriority = features(w)[5]; 

भंडार एक तार्किक संदर्भ। संग्रहीत वस्तु एक वेक्टर को संदर्भित करती है जो अब मौजूद नहीं है। इसका उपयोग करने के बाद अपरिभाषित व्यवहार होता है।

इसके बजाय करते

bool const highPriority = features(w)[5]; 

या

auto const highPriority = !!features(w)[5]; 

या, के रूप में स्कॉट – सिफारिश की गई है लेकिन यह मेरी स्वाद – एक static_cast का उपयोग के लिए अभी तक बहुत वर्बोज़ है।

संग्रहीत वस्तु अब bool है।

एक ही घोषणा व्यक्त करने के इन तीन तरीकों के बीच कोई कार्यात्मक अंतर नहीं है। केवल अंतर ही गैर-कार्यात्मक हैं: मेरी राय में static_cast की अनावश्यक क्रियाशक्ति, और एक संभावना है कि !! एक सामान्य संकलक से प्रदर्शन के बारे में मूर्खतापूर्ण चेतावनी को दबा सकता है।

0

जब आप ऑटो का उपयोग करते हैं, तो ऑटो इसे उच्च प्राथमिकता द्वारा लौटाए गए प्रकार के रूप में घटा देता है जो एक बूल का संदर्भ है।बात यह है कि, उच्च प्राथमिकता एक बूल का संदर्भ नहीं देती है लेकिन एक std :: vector :: संदर्भ वस्तु। ('संदर्भ' std :: वेक्टर के अंदर एक नेस्टेड कक्षा है)। std :: vector :: संदर्भ एक "प्रॉक्सी क्लास" है, एक वर्ग जो किसी अन्य प्रकार के व्यवहार को अनुकरण करता है। न केवल यह एक प्रॉक्सी वर्ग है बल्कि एक "अदृश्य" प्रॉक्सी वर्ग है। इस तरह के वर्ग ऑटो के साथ अच्छी तरह से काम नहीं करते हैं। ऑटो अदृश्य प्रॉक्सी वर्ग के प्रकार को सही ढंग से कम नहीं कर सकता है। लेकिन static_cast एक ऊन में उच्च प्राथमिकता रूपांतरण को मजबूर करता है। यह अपरिभाषित व्यवहार से बचाता है।

+0

मैंने यही कहा। मैंने 2 संभावित समाधानों के लिए पूछा और क्यों स्कॉट मेयर्स पहले एक – DawidPi

+0

पसंद करते हैं वह इसे पसंद नहीं करते हैं। इसमे अंतर है। उनके शब्द ... "कास्ट अभिव्यक्ति के प्रकार को बूल में बदलता है, जो ऑटो तब उच्च प्राथमिकता के प्रकार के रूप में कटौती करता है। रनटाइम पर, std :: vector :: संदर्भ वस्तु std :: vector से लौटाई गई है: : ऑपरेटर [] उस बूल के रूपांतरण को निष्पादित करता है जो इसका समर्थन करता है ... " तो बाकी सभी के लिए पहले एक बूल में बदलने के लिए स्थैतिक कलाकार आवश्यक है। – dspfnder

+1

बिल्कुल वही कलाकार निष्पादित किया जाता है, जब आप 'बूल हाईप्रियो' कहते हैं ... पहले और दूसरे प्रयास में निष्पादन में कोई अंतर नहीं होता है। दोनों समाधानों में कास्ट बनाया जाता है और यह वही कलाकार है। एक स्पष्ट है कि यह एकमात्र अंतर है। परिणाम वही है। – DawidPi

संबंधित मुद्दे