অনুসন্ধানের ফলাফল পাওয়া না গেলে একটি "নুল" অবজেক্টটি ফিরিয়ে দিন


95

আমি সি ++ তে বেশ নতুন তাই আমি যখন শিখছি তখন অনেকগুলি জাভা-ইসেমস দিয়ে ডিজাইনের প্রবণতা রাখি। যাইহোক, জাভাতে, যদি আমার একটি 'অনুসন্ধান' পদ্ধতিযুক্ত ক্লাস থাকে যা একটি নির্দিষ্ট প্যারামিটারের সাথে মেলে এমন একটি বস্তু Tথেকে ফিরে আসে Collection< T >, আমি সেই বস্তুটি ফিরিয়ে দেব এবং যদি সংগ্রহটিতে বস্তুটি পাওয়া না যায়, তবে আমি ফিরে আসতাম null। তারপরে আমার কলিং ফাংশনে আমি কেবল যাচাই করতামif(tResult != null) { ... }

সি ++ এ, আমি সন্ধান করছি যে nullঅবজেক্টটি উপস্থিত না থাকলে আমি কোনও মান ফিরিয়ে দিতে পারি না। আমি কেবল টি টাইপের একটি 'সূচক' ফিরিয়ে দিতে চাই যা কলিং ফাংশনটি জানিয়ে দেয় যে কোনও বস্তু পাওয়া যায় নি। আমি একটি ব্যতিক্রম ছুঁড়ে দিতে চাই না কারণ এটি সত্যই ব্যতিক্রমী পরিস্থিতি নয়।

এই মুহুর্তে আমার কোডটি দেখতে এমন দেখাচ্ছে:

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
ক্যাসাবেল

উত্তর:


72

সি ++ এ, তথ্যসূত্রগুলি নਾਲ হতে পারে না। যদি কিছু না পাওয়া যায় তবে আপনি optionচ্ছিকভাবে নাল ফিরে আসতে চান, আপনাকে কোনও পয়েন্টারটি ফেরত দিতে হবে, কোনও রেফারেন্স নয়:

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পাশাপাশি কোনও অ- গুণকে ফিরিয়ে দেওয়া ))


4
ধন্যবাদ যাইহোক, এটি কি এই জাতীয় রুটিন ডিজাইনের কোনও গ্রহণযোগ্য উপায়?
অ্যাডুরিক

6
@ অ্যাডুরিক: হ্যাঁ তথ্যসূত্রগুলি বোঝায় যে ফলাফলটি থাকতে হবে। পয়েন্টারগুলি বোঝায় যে ফলাফলটির অস্তিত্ব থাকতে পারে।
বিল

7
শুধু কৌতূহলী, আমরা কি এখন সি ++ 11 এর nullptrপরিবর্তে ফিরে আসব NULL?
বর্ণালী

4
হ্যাঁ সর্বদা সি ++ 11 এবং তারপরে NULL এর উপরে নালপ্টর ব্যবহার করুন। আপনার যদি পূর্ববর্তী সংস্করণগুলির সাথে পিছনের দিকের সামঞ্জস্যপূর্ণ হওয়া দরকার তবে তা করবেন না
কনরাড জোন্স

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&>();
    }

একটি উত্সাহ :: alচ্ছিক এখানে ঠিক কি চলছে তা বোঝায় এবং এ জাতীয় কোনও বৈশিষ্ট্য পাওয়া গেছে কিনা তা খতিয়ে দেখার সহজ পদ্ধতি রয়েছে।


পার্শ্ব নোট: std :: optionচ্ছিক সম্প্রতি সি ++ 17 এ ভোট দেওয়া হয়েছে, সুতরাং অদূর ভবিষ্যতে এটি একটি "স্ট্যান্ডার্ড" জিনিস হবে।


+1 আমি প্রথমে বুস্ট :: বিকল্প প্রথমে উল্লেখ করব এবং সংক্ষেপে অন্যান্য বিকল্পগুলি উল্লেখ করব।
নেমানজা ত্রিফুনোভিচ

ইয়া আমি বুস্ট :: বৈকল্পিক কোথাও উল্লিখিত দেখেছি কিন্তু আমি ভাবছিলাম যে এটির জন্য খুব বেশি ওভারহেডের প্রয়োজন required যদি এটি ব্যবহার করা এই ধরণের সমস্যার সর্বোত্তম পন্থা হয় তবে আমি এটি ব্যবহার শুরু করব।
অ্যাডুরিক

boost::optionalখুব বেশি ওভারহেড জড়িত না (কোনও গতিশীল বরাদ্দ নেই), এ কারণেই এটি এত দুর্দান্ত। পলিমারফিক মান সহ এটি ব্যবহারের জন্য মোড়ানোর রেফারেন্স বা পয়েন্টারগুলির প্রয়োজন।
ম্যাথিউ এম।

4
নিবন্ধন করুন সম্ভবত ওভারহেড অ্যাডুরিকটি উল্লেখ করেছেন যে এটি পারফরম্যান্স নয়, তবে প্রকল্পের মধ্যে একটি বাহ্যিক গ্রন্থাগার অন্তর্ভুক্ত করার ব্যয়।
স্বুগান

আমার উত্তরের একটি সংযোজন: নোট করুন যে একটি স্ট্যান্ড উপাদান হিসাবে alচ্ছিক মানিককরণের আগে একটি আন্দোলন চলছে, সম্ভবত এটির জন্য সি ++ 17 কি হতে পারে। সুতরাং এই কৌশল সম্পর্কে জানার মূল্য।
কাজ ড্রাগন

22

আপনি সহজেই একটি স্থির অবজেক্ট তৈরি করতে পারেন যা কোনও নুল ফেরতের প্রতিনিধিত্ব করে।

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;

নোডনুল এট্রিক টাইপ হওয়া উচিত নয়?
অ্যাডুরিক

3

আপনি যদি কোনও 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

আপনি এখানে নুল ফেরত দিতে পারবেন না এর কারণ হ'ল আপনি নিজের রিটার্নের ধরনটি যেমন ঘোষণা করেছেন Attr&। পেছন পেছন &ফেরত মানকে "রেফারেন্স" করে তোলে, যা মূলত একটি বিদ্যমান বস্তুর কাছে নিশ্চিত-না-হওয়া-নাল পয়েন্টার। আপনি যদি নাল ফিরে দিতে সক্ষম হতে চান তবে এতে পরিবর্তন Attr&করুন Attr*


0

আপনি ফিরতে পারবেন না NULLকারণ ফাংশনটির রিটার্ন টাইপ হ'ল একটি অবজেক্ট referenceএবং একটি নয় pointer


-3

আপনি এটি চেষ্টা করতে পারেন:

return &Type();

6
এই কোড স্নিপেট একটি ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে, যদিও সত্যিই আপনার পোস্টের মান উন্নত করতে সহায়তা করে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, এবং সেই লোকেরা আপনার কোড পরামর্শের কারণগুলি জানেন না।
নাথান অলিভার

এটি সম্ভবত পদ্ধতি স্ট্যাকের কোনও বস্তুর একটি মৃত রেফারেন্স ফিরিয়ে দেয়, তাই না?
এমপ্রোমনেট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.