यदि खोज परिणाम नहीं मिला, तो "NULL" ऑब्जेक्ट लौटाएं


94

मैं C ++ के लिए बहुत नया हूं, इसलिए जब मैं सीख रहा हूं तो मैं बहुत सारे जावा-आईएमएस के साथ डिजाइन करता हूं। वैसे भी, जावा में, यदि मेरे पास एक 'खोज' पद्धति है, जो उस ऑब्जेक्ट Tसे Collection< T >एक विशिष्ट पैरामीटर से मेल खाते हुए लौटेगी, तो मैं उस वस्तु को वापस कर दूंगा और यदि वस्तु संग्रह में नहीं मिली, तो मैं वापस लौटूंगा null। फिर मेरे कॉलिंग फंक्शन में मैं सिर्फ जाँच करूँगाif(tResult != null) { ... }

C ++ में, मुझे पता चल रहा है कि nullयदि वस्तु मौजूद नहीं है तो मैं एक मान नहीं लौटा सकता । मैं केवल टाइप T के 'इंडिकेटर' को वापस करना चाहता हूं जो कॉलिंग फ़ंक्शन को सूचित करता है कि कोई ऑब्जेक्ट नहीं मिला है। मैं एक अपवाद नहीं फेंकना चाहता क्योंकि यह वास्तव में एक असाधारण परिस्थिति नहीं है।

यह मेरा कोड अभी जैसा दिखता है:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

मैं इसे कैसे बदल सकता हूं ताकि मैं उस तरह का मार्कर दे सकूं?


6
अपवाद और NULL हमेशा एकमात्र समाधान नहीं हैं। आप अक्सर पाया नहीं लौटने का संकेत करने के लिए एक मूल्य चुन सकते हैं: उदाहरण के लिए, यदि कोई तत्व मैच नहीं करता है तो std::find(first, last, value)रिटर्न last
कास्कैबेल

जवाबों:


70

C ++ में, संदर्भ शून्य नहीं हो सकते। यदि आप वैकल्पिक रूप से अशक्त होना चाहते हैं यदि कुछ नहीं मिला है, तो आपको एक सूचक को वापस करने की आवश्यकता है, संदर्भ नहीं:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

अन्यथा, यदि आप संदर्भ द्वारा लौटने पर जोर देते हैं, तो आपको एक अपवाद फेंक देना चाहिए यदि विशेषता नहीं मिली है।

(वैसे, मैं आपकी विधि के बारे में थोड़ा चिंतित हूं constऔर एक गैर- constविशेषता को वापस कर रहा हूं। दार्शनिक कारणों से, मैं लौटने का सुझाव दूंगा const Attr *। यदि आप भी इस विशेषता को संशोधित करना चाहते हैं, तो आप गैर- constविधि से ओवरलोड कर सकते हैं। एक गैर- constविशेषता को भी लौटाना ।)


2
धन्यवाद। वैसे, क्या यह इस तरह की दिनचर्या को डिजाइन करने का एक स्वीकृत तरीका है?
एडुरिक

6
@ आदिक: हाँ। संदर्भ का अर्थ है कि परिणाम मौजूद है। संकेत का मतलब है कि परिणाम मौजूद नहीं हो सकता है।
बिल

7
बस जिज्ञासु, क्या हम अब c ++ 11 के nullptrबजाय वापस लौटेंगे NULL?
स्पेक्ट्रल

1
हां हमेशा C ++ 11 और बाद में NULL से अधिक nullptr का उपयोग करें। यदि आपको बाली संस्करणों के साथ पीछे की ओर संगत होना चाहिए, तो नहीं
कोनराड जोन्स

56

यहाँ कई संभावित उत्तर हैं। आप कुछ ऐसा करना चाहते हैं जो मौजूद हो। यहाँ कुछ विकल्प दिए गए हैं, जिनमें से मेरी पसंद सबसे कम पसंद की गई है:

  • संदर्भ द्वारा लौटें, और संकेत अपवाद द्वारा नहीं मिल सकता है।

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

यह संभावना है कि विशेषताओं को नहीं ढूंढना निष्पादन का एक सामान्य हिस्सा है, और इसलिए बहुत असाधारण नहीं है। इसके लिए हैंडलिंग शोर होगा। एक शून्य मान नहीं लौटाया जा सकता क्योंकि यह अशक्त व्यवहार के लिए अशक्त संदर्भ है।

  • पॉइंटर से लौटें

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

यह जांचना आसान है कि क्या getAttribute का एक परिणाम एक गैर-पूर्ण सूचक होगा, और यह बग का एक आसान स्रोत है।

  • Boost.Optional का उपयोग करें

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

एक बढ़ावा :: वैकल्पिक यह बताता है कि यहाँ क्या चल रहा है, और इस तरह की विशेषता के निरीक्षण के लिए आसान तरीके हैं।


साइड नोट: std :: वैकल्पिक को हाल ही में C ++ 17 में वोट किया गया था, इसलिए यह निकट भविष्य में एक "मानक" चीज होगी।


+1 मैं केवल बूस्ट का उल्लेख करूंगा: वैकल्पिक पहला, और केवल कुछ अन्य विकल्पों का संक्षेप में उल्लेख करें।
नेमेनजा ट्रिफ़ुनोविक

हां मैंने बढ़ावा देखा: कहीं वैकल्पिक उल्लेख किया गया था लेकिन मैं सोच रहा था कि इसके लिए बहुत अधिक ओवरहेड की आवश्यकता है। यदि इसका उपयोग इस प्रकार की समस्याओं के लिए सबसे अच्छा तरीका है, तो मैं इसका उपयोग करना शुरू कर दूंगा।
एडुरिक

boost::optionalज्यादा ओवरहेड (कोई गतिशील आवंटन) शामिल नहीं करता है, यही कारण है कि यह बहुत अच्छा है। पॉलिमॉर्फिक मूल्यों के साथ इसका उपयोग करने के लिए संदर्भों या बिंदुओं को लपेटने की आवश्यकता होती है।
मैथ्यू एम।

2
@MatthieuM। यह संभावना है कि ओवरहेड एड्यूरिक प्रदर्शन नहीं था, लेकिन परियोजना में एक बाहरी पुस्तकालय को शामिल करने की लागत थी।
सवोगन

मेरे उत्तर के लिए एक परिशिष्ट: ध्यान दें कि एक एसटीडी घटक के रूप में वैकल्पिक रूप से मानकीकृत करने के लिए एक आंदोलन है, संभवतः सी ++ 17 के लिए क्या हो सकता है। तो यह इस तकनीक के बारे में जानने लायक है।
काज़ ड्रैगन

22

आप आसानी से एक स्थिर ऑब्जेक्ट बना सकते हैं जो NULL रिटर्न का प्रतिनिधित्व करता है।

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

और कहीं एक स्रोत फ़ाइल में:

static Attr AttrNull;

क्या NodeNull Attr का नहीं होना चाहिए?
17:14 बजे

3

यदि आप NULLरिटर्न वैल्यू चाहते हैं तो आपको संदर्भों के बजाय पॉइंटर्स का उपयोग करने की आवश्यकता है।

संदर्भ स्वयं नहीं हो सकते NULL

(भविष्य के टिप्पणी पोस्टरों पर ध्यान दें: हाँ, आपके पास एक संदर्भ का पता हो सकता है यदि आप वास्तव में कोशिश करते हैं तो NULL होना चाहिए)।

संदर्भ और संकेत के बीच अंतर की एक सूची के लिए मेरा जवाब यहां देखें


2

जैसा कि आप समझ चुके हैं कि आप इसे जावा (या सी #) में नहीं कर सकते हैं। यहां एक और सुझाव दिया गया है, आप ऑब्जेक्ट के संदर्भ में एक तर्क और रिटर्न बूल वैल्यू के रूप में पास कर सकते हैं। यदि परिणाम आपके संग्रह में पाया जाता है, तो आप इसे पास किए जा रहे संदर्भ को असाइन कर सकते हैं और 'सही' लौटा सकते हैं, अन्यथा 'गलत' लौटा सकते हैं। कृपया इस कोड पर विचार करें।

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string token, Operator& op)
{
    bool val = false;

    OPERATORS_MAP::iterator it = m_operators.find(token);
    if (it != m_operators.end())
    {
        op = it->second;
        val = true;
    }
    return val;
}

उपरोक्त फ़ंक्शन को कुंजी 'टोकन' के विरुद्ध ऑपरेटर को खोजना होगा, यदि वह इसे सही पाता है और पैरामीटर ऑपरेटर और ऑप को मान असाइन करता है।

इस रूटीन के लिए कॉलर कोड कुछ इस तरह दिखता है

Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
    //Do something here if true is returned.
}

1

कारण यह है कि आप NULL यहाँ नहीं लौट सकते क्योंकि आपने अपना रिटर्न प्रकार घोषित कर दिया है Attr&। अनुगामी &रिटर्न मान को एक "संदर्भ" बनाता है, जो मूल रूप से एक मौजूदा वस्तु के लिए गारंटी-से-टू-नल सूचक है। यदि आप अशक्त लौटने में सक्षम होना चाहते हैं, तो बदल Attr&दें Attr*


0

आप लौटने में असमर्थ हैं NULLक्योंकि फ़ंक्शन का रिटर्न प्रकार एक ऑब्जेक्ट है referenceन कि ए pointer


-3

आप यह कोशिश कर सकते हैं:

return &Type();

6
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और उन लोगों को आपके कोड सुझाव के कारणों का पता नहीं चल सकता है।
नाथनऑलिवर

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