क्या मैं (पॉइंटर) का उपयोग कर सकता हूं यदि (पॉइंटर! = NULL) के बजाय?


171

क्या NULLकेवल लिखने से नहीं होने के लिए एक संकेतक की जांच करना सुरक्षित है if(pointer)या मुझे उपयोग करना है if(pointer != NULL)?


13
सच्चाई यह है कि, यदि आप एक स्पष्ट जाँच का उपयोग करने जा रहे हैं, तो यह उतना ही प्रभावी है - और अक्सर पसंद किया जाता है - 0या उसके विरुद्ध परीक्षण करना nullptr। ( NULLएक C'ism है, और एक हेडर फ़ाइल शामिल करने की आवश्यकता है।)
cHao

5
@danijar आप आधुनिक C ++ में nullptr का उपयोग कर सकते हैं।
सर्वाइवलमैचिन

9
@cHao "C के साथ संगतता के लिए लक्ष्य" में कहाँ है?
qdii

5
@danijar: हां, आपको यहां NULLसे C ++ में उपयोग नहीं करना चाहिए क्योंकि NULLकार्यान्वयन निर्भर मैक्रो है जो आपको अस्पष्ट व्यवहार दे सकता है।
आलोक सेव

3
हालांकि यह 'यदि' मामला नहीं है, तो इस आइडोन लाइव डेमो को देखें कि क्यों आपको C ++ में संकेत के लिए "NULL" और "0" से बचना चाहिए: ideone.com/tbvXNs
kfsone

जवाबों:


197

आप ऐसा कर सकते हैं; नल पॉइंटर को स्पष्ट रूप से बूलियन झूठ में परिवर्तित किया जाता है जबकि गैर-नल बिंदुओं को सत्य में परिवर्तित किया जाता है। C ++ 11 मानक से, बूलियन रूपांतरण पर अनुभाग :

अंकगणित, अनकैप्ड एन्यूमरेशन, पॉइंटर या पॉइंटर टू मेंबर टाइप के प्रील्यू को टाइप के प्रीलव्यू में बदला जा सकता है bool। शून्य मान, अशक्त सूचक मान या अशक्त सदस्य सूचक मान परिवर्तित किया जाता है false; किसी भी अन्य मूल्य में परिवर्तित किया जाता है true । प्रकार का एक प्रचलन प्रकार के एक प्रचलन में std::nullptr_t परिवर्तित किया जा सकता है bool ; परिणामस्वरूप मूल्य है false


42

हाँ तुम कर सकते हो।

  • एक अशक्त सूचक को झूठे रूप में परिवर्तित किया जाता है
  • एक गैर-शून्य सूचक को सत्य में परिवर्तित किया जाता है।

यह C ++ मानक रूपांतरण का हिस्सा है, जो बुलियन रूपांतरण खंड में आता है :

§ 4.12 बूलियन रूपांतरण

अंकगणित, अनकैप्ड एन्यूमरेशन, पॉइंटर या पॉइंटर टू मेंबर टाइप के प्रील्यूव को टाइप बूल के प्रीलव्यू में बदला जा सकता है। शून्य मान, अशक्त सूचक मान या अशक्त सदस्य सूचक मान मिथ्या में परिवर्तित हो जाता है; किसी अन्य मान को सत्य में परिवर्तित किया जाता है। प्रकार std का एक प्रचलन :: nullptr_t को प्रकार बूल के एक प्रचलन में परिवर्तित किया जा सकता है; परिणामी मूल्य गलत है।


29

हाँ तुम कर सकते हो। वास्तव में, मैं if(pointer)इसका उपयोग करना पसंद करता हूं क्योंकि एक बार पढ़ने और लिखने के बाद आपको इसकी आदत पड़ जाती है।

यह भी ध्यान दें कि C ++ 11 को पेश nullptrकिया गया है जिसे अधिक पसंद किया गया है NULL


10
एक सूचक एक बूलियन अभिव्यक्ति नहीं है। यह अंतर्निहित रूप से परिवर्तित है। अगर पढ़ने के लिए बेहतर है कि आपको इस रूपांतरण को याद रखना है तो आपकी राय है। यह सिर्फ एक तरह की कोडिंग शैली है।
हार्पर

7
@ आप कह सकते हैं कि यह एक कोडिंग शैली है। लेकिन आप if(som_integer)बनाम तर्क को लागू कर सकते if(some_integer != 0)हैं क्योंकि पूर्णांक भी बूलियन नहीं हैं, है ना? मैं बचना पसंद करता हूं 0या NULLअगर-स्टेटमेंट में।
यू हाओ

13
मैं सहमत हूँ कि यह केवल कोडिंग शैली की बात है। मैं if (pointer)खुद को पसंद करने के लिए आया हूं, लेकिन if (ptr != nullptr)मुझे पूरी तरह से वैध लगता है। दूसरी ओर, अगर मैंने अपनी टीम पर किसी को देखा, जिसने लिखा कि if (some_integer)मैं उन्हें इसे बदल दूंगा if (some_integer != 0)। हालाँकि, मैं यह दिखावा नहीं करूंगा कि यह मेरी ओर से अपेक्षाकृत मनमानी पसंद नहीं है - मैं केवल पॉइंटर्स और पूर्णांकों का इलाज नहीं करना पसंद करता हूं।
जोएल

1
@YuHao और चूंकि यह कोड शैली है, इसलिए मैं "यह पसंद नहीं है" लेकिन "मुझे पसंद है" बताएगा।
हार्पर

5
@ franji1 फिर कैसे if(isReady) if(filePtr) if(serviceNo)? उद्देश्य पर खराब परिवर्तनीय नाम बनाना इस मामले में बहुत मायने नहीं रखता है। वैसे भी मैं पहले ही आपकी बात मान गया और इसे समझ गया, लेकिन मैं अपनी खुद की कोडिंग शैली का उपयोग करने पर जोर दे सकता हूं, ठीक है?
यू हाओ

13

प्रश्न का उत्तर दिया गया है, लेकिन मैं अपने बिंदुओं को जोड़ना चाहूंगा।

मैं हमेशा के if(pointer)बजाय if(pointer != NULL)और के if(!pointer)बजाय पसंद करेंगे if(pointer == NULL):

  • यह सरल है, छोटा है
  • एक छोटी गाड़ी कोड लिखने के लिए कम संभावना है, मान लें कि अगर मैंने समानता वाले ऑपरेटर ऑपरेटर ==को =
    if(pointer == NULL)गलत वर्तनी दी है if(pointer = NULL)तो मैं इससे बचूंगा, सबसे अच्छा है if(pointer)
    (मैंने एक उत्तर में कुछ योडा स्थिति का भी सुझाव दिया , लेकिन यह अलग मामला है)

  • इसी तरह while (node != NULL && node->data == key), मैं बस लिखूंगा while (node && node->data == key)कि मेरे लिए और अधिक स्पष्ट है (दिखाता है कि शॉर्ट-सर्किट का उपयोग करके)।

  • (मूर्खतापूर्ण कारण हो सकता है) क्योंकि NULL एक मैक्रो है, यदि किसी अन्य मान के साथ गलती से किसी एक को फिर से परिभाषित करें।

6
= = के बजाय == लगभग हमेशा एक कंपाइलर चेतावनी उत्पन्न करता है, उन दिनों में जब लोग इसका इस्तेमाल नहीं करेंगे (NULL == ptr)
paulm

@paulm कि मैंने इस बिंदु को इसके Yoda कंडीशन में जोड़ा है कुछ लोग इसे इसके कम पठनीय के रूप में पसंद नहीं करते हैं।
ब्रिजेश चौहान

2
(boolean expression)? true : falseपूरी तरह से व्यर्थ है। अभिव्यक्ति या तो या का मूल्यांकन करती trueहै false; आप जो कहते हैं, "अगर यह सच है, तो मुझे सच दे दो, अगर यह गलत है, तो मुझे गलत दो"। संक्षेप में: यह पूरी तरह से बूलियन अभिव्यक्ति के बराबर है। ध्यान दें कि node == NULLएक बूलियन अभिव्यक्ति है। BTW, आपके दो कार्यान्वयन एक दूसरे के बिल्कुल विपरीत हैं। या तो आप !=पहले में चाहते हैं , या !दूसरे में केवल एक ।
celtschk

BTW, के =बजाय के खिलाफ एक संभव संरक्षण ==अपने चर बनाने के लिए constजब भी संभव है। उदाहरण के लिए, आप अपने फ़ंक्शन को इस रूप में परिभाषित कर सकते हैं isEmnpy(node* const head) { ... }, और फिर संकलक इसे संकलित करने से इंकार कर देगा यदि आपने गलती से लिखा node = NULLहै node == NULL। बेशक जो केवल उन चरों के लिए काम करता है जिन्हें आपको वास्तव में बदलने की आवश्यकता नहीं है।
celtschk

2
क्योंकि स्मार्ट पॉइंटर क्लासेस के T* get() constबजाय operator T*() constनिहित रूपांतरणों से बचने के लिए है। वे हालांकि एक है operator bool() const
स्टेलारवर्टेक्स

13

स्पष्ट रूप से NULL के लिए जाँच करने से आप जो करने की कोशिश कर रहे हैं उस पर कंपाइलर को संकेत मिल सकता है, कम त्रुटि वाले होने के लिए अग्रणी।

यहां छवि विवरण दर्ज करें


8

हाँ तुम कर सकते हो। शून्य से मानों की तुलना करने की क्षमता अंतर्निहित रूप से C से विरासत में मिली है, और C ++ के सभी संस्करणों में है। आप if (!pointer)NULL के लिए पॉइंटर्स चेक करने के लिए भी उपयोग कर सकते हैं ।


2

शून्य बिंदुओं के लिए प्रासंगिक उपयोग के मामले हैं

  • एक गहरे पेड़ के नोड की तरह कुछ के लिए पुनर्निर्देशन, जो मौजूद नहीं हो सकता है या अभी तक जुड़ा नहीं है। यह एक ऐसी चीज है जिसे आपको हमेशा एक समर्पित वर्ग में घनिष्ठता से रखना चाहिए, इसलिए पठनीयता या संक्षिप्तता यहां एक मुद्दा नहीं है।
  • गतिशील जाति। बेस-क्लास पॉइंटर को किसी विशेष व्युत्पन्न वर्ग के लिए कास्टिंग करना (ऐसा कुछ जिसे आपको फिर से टालने की कोशिश करनी चाहिए, लेकिन कई बार आवश्यक लग सकता है) हमेशा सफल होता है, लेकिन परिणाम में शून्य वर्ग मेल नहीं खाता है। इसे जांचने का एक तरीका है

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
    if(derived_ptr != nullptr) { ... }

    (या, अधिमानतः auto derived_ptr = ...)। अब, यह बुरा है, क्योंकि यह सुरक्षा की रक्षा करने वाले ifब्लॉक के दायरे से बाहर (संभवतः अमान्य, शून्य) व्युत्पन्न सूचक को छोड़ देता है । यह आवश्यक नहीं है, क्योंकि C ++ आपको एक ifकॉनडिशन के अंदर बूलियन-परिवर्तनीय चर पेश करने की अनुमति देता है :

    if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }

    जो न केवल छोटा और गुंजाइश-सुरक्षित है, यह उसके इरादे में भी अधिक स्पष्ट है: जब आप एक अलग-अलग स्थिति में नल की जांच करते हैं, तो पाठक आश्चर्यचकित करता है "ठीक है, इसलिए derived_ptrयहाँ शून्य नहीं होना चाहिए ... अच्छा, क्यों? यह शून्य हो सकता है? जबकि एक लाइन संस्करण बहुत स्पष्ट रूप से कहते हैं, "यदि आप सुरक्षित रूप से डाल सकता base_ptrकरने के लिए Derived*है, तो के लिए इसका इस्तेमाल करते हैं ..."।

    वही काम करता है जो किसी अन्य संभावित-विफलता ऑपरेशन के लिए भी होता है जो एक पॉइंटर लौटाता है, हालांकि आईएमओ आपको आम तौर पर इससे बचना चाहिए: यह boost::optionalसंभव है कि पॉइंटर्स के बजाय संभवतः विफल संचालन के परिणामों के लिए "कंटेनर" की तरह कुछ का उपयोग करें ।

तो, अशक्त संकेत के लिए मुख्य उपयोग के मामले हमेशा निहित कलाकारों शैली की भिन्नता में लिखा जाना चाहिए अगर, मैं एकरूपता बनाए रखने के लिए यह अच्छा करने के लिए कहेंगे हमेशा इस शैली का उपयोग, अर्थात् मैं के लिए की वकालत करता हूँ if(ptr)से अधिक if(ptr!=nullptr)


मुझे डर है कि मुझे एक विज्ञापन के साथ समाप्त होना है: if(auto bla = ...)वाक्यविन्यास वास्तव में ऐसी समस्याओं के वास्तविक समाधान के लिए थोड़ा बोझिल सन्निकटन है, पैटर्न मिलान । आप पहले कुछ एक्शन (जैसे पॉइंटर डालने) को क्यों बाध्य करेंगे और फिर विचार करेंगे कि कोई विफलता हो सकती है ... मेरा मतलब है, यह हास्यास्पद है, है ना? यह पसंद है, आपके पास कुछ खाद्य पदार्थ हैं और सूप बनाना चाहते हैं। आप इसे रस निकालने के लिए अपने सहायक को सौंपते हैं, अगर यह एक नरम सब्जी होती है। आप इसे पहले नहीं देखते हैं। जब आपके पास एक आलू होता है, तब भी आप इसे अपने सहायक को दे देते हैं, लेकिन वे इसे एक असफल नोट के साथ आपके चेहरे पर वापस थप्पड़ मारते हैं। आह, अनिवार्य प्रोग्रामिंग!

बहुत बेहतर: सही उन सभी मामलों पर विचार करें जिनसे आप मुठभेड़ कर सकते हैं। फिर उसके अनुसार कार्य करें। हास्केल:

makeSoupOf :: Foodstuff -> Liquid
makeSoupOf p@(Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
 | isSoft vegetable  = squeeze vegetable <> salt
makeSoupOf stuff  = boil (throwIn (water<>salt) stuff)

हास्केल के पास विशेष उपकरण भी हैं, जब वास्तव में विफलता की एक गंभीर संभावना है (साथ ही अन्य सामान की एक पूरी गुच्छा के लिए): सनक। लेकिन यह उन लोगों को समझाने की जगह नहीं है।

⟨/ Advert⟩


1
मैं इस अंतरिम पेंच में केवल एक वाक्य देख सकता हूं जो वास्तव में प्रश्न का उत्तर देता है।
लोर्न जू के मार्किस

@ ईजेपी: यदि आप प्रश्न को शाब्दिक रूप से लेते हैं (" क्या मैं उपयोग कर सकता हूं"), तो इसका स्पष्ट रूप से उत्तर नहीं दिया गया है (उत्तर बस "हां" है)। मैं क्यों ओ पी के लिए उचित कारण बता करने की कोशिश की जाना चाहिए तथ्य प्रयोग में if(ptr)के बजाय if(ptr != nullptr), जो करने के लिए नहीं है पास बहुत-सी कहने के लिए।
लेफ्टरनैबाउट

1

हां बिल्कुल! वास्तव में, लेखन अगर (पॉइंटर) लिखने का एक और अधिक सुविधाजनक तरीका है बजाय (पॉइंटर! = NULL) क्योंकि: 1. डिबग करना आसान है 2. समझना आसान है 3. अगर गलती से, NULL का मान परिभाषित किया गया है, तब भी कोड क्रैश नहीं होगा



0

जैसा कि अन्य पहले से ही अच्छी तरह से उत्तर दे चुके हैं, वे दोनों विनिमेय हैं।

बहरहाल, यह ध्यान देने योग्य है कि ऐसा कोई मामला हो सकता है जहाँ आप स्पष्ट कथन का उपयोग करना चाहें pointer != NULL

Https://stackoverflow.com/a/60891279/2463963 भी देखें


-1

हां, आप इसे हमेशा 'IF' कंडीशन के रूप में कर सकते हैं, जब इसके अंदर की स्थिति सही होती है। C के पास बूलियन रिटर्न प्रकार नहीं होता है और इस प्रकार गैर-शून्य मान लौटाता है जब स्थिति सच होती है, जबकि रिटर्न 0 'जब भी' IF 'की स्थिति झूठी होती है। डिफ़ॉल्ट रूप से लौटाया गया शून्य शून्य मान 1. इस प्रकार, कोड लिखने के दोनों तरीके सही हैं जबकि मैं हमेशा दूसरे को पसंद करूंगा।


1
यदि मुझे सही याद है तो डिफ़ॉल्ट रूप से गैर-शून्य मान अपरिभाषित है।
लोर्न जू के मार्किस

-1

मुझे लगता है कि अंगूठे के नियम के रूप में, यदि आपकी अभिव्यक्ति को फिर से लिखा जा सकता है

const bool local_predicate = *if-expression*;
if (local_predicate) ...

ऐसा नहीं है कि यह कोई चेतावनी का कारण बनता है, तो यह कि अगर अभिव्यक्ति के लिए पसंदीदा शैली होनी चाहिए । (मुझे लगता है मैं चेतावनी मिलती है, जब मैं एक पुराने सी आवंटित पता BOOL( #define BOOL int) एक सी ++ के लिए bool, अकेले संकेत दिए गए हैं।)


-1

"क्या ये सुरक्षित है..?" भाषा मानक और उत्पन्न कोड के बारे में एक प्रश्न है।

"एक अच्छा अभ्यास है?" एक सवाल है कि बयान के किसी भी मनमाना मानव पाठक द्वारा कथन को कितनी अच्छी तरह से समझा जाता है। यदि आप यह प्रश्न पूछ रहे हैं, तो यह बताता है कि "सुरक्षित" संस्करण भविष्य के पाठकों और लेखकों के लिए कम स्पष्ट है।


मेरा इरादा यह पूछना था कि क्या यह सुरक्षित है। ऊपर मैंने उस शब्द का इस्तेमाल किया। हालाँकि, आपने यहां जो लिखा है, वह सवाल का जवाब नहीं है। इसके बजाय, यह सवाल के तहत एक टिप्पणी होनी चाहिए। आप उत्तर को हटा सकते हैं और फिर प्रश्न के तहत एक टिप्पणी जोड़ सकते हैं।
दानीझर

@danijar क्या आपको याद नहीं है कि जब आप StackOverflow में नए थे और सफलता के बिना 'टिप्पणी' अनुभाग की खोज की थी? 7 प्रतिष्ठा वाला कोई व्यक्ति ऐसा नहीं कर सकता।
Broxzier

@JimBalter जो बहुत भ्रामक है, क्योंकि आप दूसरों को ऐसा करते देख सकते हैं। जब मैं SO के लिए नया था तो किसी ने मुझे ऐसा करने के लिए दोषी ठहराया।
ब्रुकज़िएर

@JimBalter मैं हत्या और चोरी नहीं कर रहा हूँ। मैं डानिजर को बता रहा था कि फ्रेड मिशेल एक नया उपयोगकर्ता था और टिप्पणी पोस्ट नहीं कर सकता था।
ब्रुकज़िएर

@JimBalter जो आपने आज शुरू किया। इसके अलावा आप इसके बजाय समझ नहीं रहे हैं। वह टिप्पणी केवल इस के भ्रमित होने का समर्थन कर रही है।
ब्रॉक्सज़ियर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.