"यदि" कथन में वैरिएबल को प्रारंभ करना


80

मैंने पढ़ा कि C ++ 17 में हम ifइस तरह के कथनों में वेरिएबल्स को इनिशियलाइज़ कर सकते हैं

if (int length = 2; length == 2)
    //execute something

के बजाय

int length = 2;
if (length == 2)
    //do something

हालांकि यह छोटा है, यह कोड की पठनीयता को प्रभावित करता है (विशेषकर उन लोगों के लिए जो इस नई सुविधा को नहीं जानते हैं), जो मुझे लगता है कि बड़े सॉफ्टवेयर विकास के लिए एक खराब कोडिंग अभ्यास है।

क्या कोड को छोटा बनाने के अलावा इस सुविधा का उपयोग करने का कोई फायदा है?


38
गुंजाइश की बात के अलावा?
देईदेई

10
मुझे लगता है कि किसी ने कुछ साल पहले कहा था "मैंने पढ़ा है कि C ++ 11 में, हम इस तरह से लैम्बडा स्टेटमेंट बना सकते हैं (...) हालांकि यह छोटा है, यह कोड पठनीयता को प्रभावित करता है (विशेषकर उन लोगों के लिए जो नहीं जानते हैं यह नई सुविधा), जो मुझे लगता है कि बड़े सॉफ्टवेयर विकास के लिए एक खराब कोडिंग अभ्यास है। ”
R2RT

9
मैं कहूंगा कि इसकी लंबाई समान है, छोटी नहीं है।
user7860670

5
शुद्ध राय, इसलिए उत्तर नहीं: if (int length = 2; length == 2)शायद आप पहली बार इसे देखकर आश्चर्यचकित हैं, लेकिन यह कुछ भी जटिल नहीं है कि कोई यह नहीं समझ सकता है कि दूसरी बार पहले से ही यह अब एक बड़ा आश्चर्य नहीं है और इस दायरे में सामान की घोषणा करना जहां यह है पठनीयता में योगदान करने वाले मुख्य कारकों में से एक। Imho आपका आधार गलत है;)
बड़ा_प्रति___303035818

14
उन लोगों के लिए कोड पठनीयता के बारे में चिंता करना जो उस भाषा को नहीं जानते हैं जिसमें कोड लिखा गया है (जो कि "इस नई सुविधा को नहीं जानता है" का अर्थ है) नीचे की ओर एक दौड़ है।

जवाबों:


97

यह के दायरे को सीमित करता है lengthकरने के लिए ifअकेले। इसलिए आपको वही लाभ मिलते हैं जो हमें मूल रूप से मिलते थे जब हमें लिखने की अनुमति थी

for(int i = 0; i < ... ; ++i) {
   // ...
}

चर लीक के बजाय

int i;
for(i = 0; i < ... ; ++i) {
   // ...
}

लघु जीवित चर कई कारणों से बेहतर हैं। लेकिन एक जोड़े को नाम देने के लिए:

  1. कम कुछ रहता है, कोड की असंबंधित पंक्तियों को पढ़ते समय आपको कम चीजों को ध्यान में रखना होगा। यदि iलूप या ifस्टेटमेंट के बाहर मौजूद नहीं है , तो हमें उनके बाहर इसके मूल्य को ध्यान में रखने की आवश्यकता नहीं है। और न ही हमें इसकी चिंता करने की आवश्यकता है कि कार्यक्रम के अन्य भागों के साथ बातचीत करेगा जो इसके इच्छित दायरे से बाहर हैं (जो कि iऊपर किसी अन्य लूप में पुन: उपयोग किए जाने पर हो सकता है )। यह कोड का अनुसरण करना आसान बनाता है और इसके बारे में तर्क देता है।

  2. यदि वैरिएबल के पास एक संसाधन है, तो उस संसाधन को अब कम से कम अवधि के लिए आयोजित किया जाता है। और यह बिना बाहरी घुंघराले ब्रेसिज़ है। यह भी स्पष्ट है कि संसाधन ifअकेले से संबंधित है । इसे एक प्रेरक उदाहरण के रूप में देखें

    if(std::lock_guard _(mtx); guarded_thing.is_ready()) {
    }
    

यदि आपके सहकर्मी इस सुविधा से अवगत नहीं हैं, तो उन्हें सिखाएं! प्रोग्रामर को खुश करना जो सीखना नहीं चाहते हैं, सुविधाओं से बचने के लिए एक खराब बहाना है।


12
मैं इस आखिरी वाक्य को हथियाने जा रहा हूं और इसे दो मीटर के पोस्टर पर थप्पड़ मार रहा हूं।
क्वेंटिन

3
इसके अलावा, अल्पकालिक (कसकर काटे गए) चर को बग को कम करना चाहिए क्योंकि आप गलती से किसी चर को बाद में कोड में पुन: उपयोग नहीं कर सकते हैं क्योंकि इसका उद्देश्य पूरा हो गया है।
गैलिक

1
या कमजोर सूचक के साथ:if (auto p = ptr.lock(); p && p->foo()) bar(*p);
Deduplicator

1
3. संकलक को अधिक मामलों में स्टैक स्थान का पुन: उपयोग करने की अनुमति है। (यदि आप कभी भी उदाहरण के लिए किसी बाहरी फ़ंक्शन के संदर्भ या पॉइंटर से पास होते हैं।)
TLW

बेहतर सवाल यह हो सकता है कि "इस ओवर का क्या फायदा है {int i = 2; if (i == 2) {...}}" (अतिरिक्त गुंजाइश पर ध्यान दें)
TLW

24

क्या कोड को छोटा बनाने के अलावा इस सुविधा का उपयोग करने का कोई फायदा है?

आप वैरिएबल स्कोप को कम करते हैं। यह समझ में आता है और पठनीयता बढ़ाता है, क्योंकि यह उन पहचानकर्ताओं के इलाके को मजबूत करता है जिनके बारे में आपको तर्क करने की आवश्यकता है। मैं मानता हूं कि बयानों के भीतर लंबे समय तक बयान ifसे बचा जाना चाहिए, लेकिन छोटी सामग्री के लिए, यह ठीक है।

ध्यान दें कि आप प्री-सी ++ 17 में परिणाम पर पहले से ही इनिशियलाइजेशन और ब्रांचिंग कर सकते हैं:

int *get(); // returns nullptr under some condition

if (int *ptr = get())
    doStuff();

यह किसी की व्यक्तिगत राय के अधीन है, लेकिन आप एक स्पष्ट स्थिति को अधिक पठनीय मान सकते हैं:

if (int *ptr = get(); ptr != nullptr)
    doStuff();

इसके अलावा, इस तथ्य की चर्चा करते हुए किसी विशेषता की पठनीयता के खिलाफ तर्क देना कि लोगों को इसकी आदत नहीं है खतरनाक है। कुछ बिंदु पर लोगों को स्मार्ट पॉइंटर्स के लिए इस्तेमाल नहीं किया गया था, फिर भी हम सभी आज सहमत हैं (मुझे लगता है) यह एक अच्छी बात है कि वे वहां हैं।


4
if (auto p =get ())ऑपरेटर बूल परिभाषित होने के बाद से आप उपयोग कर सकते हैं
sudo rm -rf slash

19

यदि कथन के नए रूप में कई उपयोग हैं।

वर्तमान में, इनीशलाइज़र को या तो बयान से पहले घोषित किया जाता है और परिवेश के दायरे में लीक किया जाता है, या एक स्पष्ट दायरे का उपयोग किया जाता है। नए रूप के साथ, इस तरह के कोड को अधिक कॉम्पैक्ट रूप से लिखा जा सकता है, और बेहतर स्कोप नियंत्रण कुछ पूर्ववर्ती त्रुटि-प्रवण निर्माणों को थोड़ा और अधिक मजबूत बनाता है।

इनिशियलाइज़र के साथ स्टेटमेंट के लिए ओपन स्टैंडर्ड प्रस्ताव

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

तो, संक्षेप में, यह कथन सामान्य कोड पैटर्न को सरल करता है और उपयोगकर्ताओं को स्कोप को चुस्त रखने में मदद करता है।

मुझे उम्मीद है यह मदद करेगा!


क्या आप स्पष्ट कर सकते हैं कि आप प्रस्ताव से उद्धृत कर रहे हैं? खासतौर पर दूसरा पैराग्राफ। मैं ब्लॉक-कोट्स का सुझाव देता हूं।
स्टोरीटेलर - अनसलैंडर मोनिका

धन्यवाद @StoryTeller, हां मैंने ओपन-एसटीडी के प्रस्ताव से दूसरा पैराग्राफ उद्धृत किया जो सी ++ 17 में शामिल था।
अभिषेक सिन्हा

10

चर के दायरे को कम करने के हित में एक मुहावरा है जो एक संसाधन को परिभाषित करता है केवल अगर यह निर्माण पर मान्य है (उदाहरण के लिए फ़ाइल स्ट्रीम ऑब्जेक्ट ):

if(auto file = std::ifstream("filename"))
{
    // use file here
}
else
{
    // complain about errors here
}

// The identifier `file` does not pollute the wider scope

कभी-कभी आप असफलता को प्राथमिक खंड और मान्य संसाधन खंड को असफल बनाने के लिए उस परीक्षण के तर्क को उलटने में सक्षम होना चाहते हैं else। यह पहले संभव नहीं था। लेकिन अब हम कर सकते हैं:

if(auto file = std::ifstream("filename"); !file)
{
    // complain about errors here
}
else
{
    // use file here
}

एक उदाहरण एक अपवाद फेंक सकता है:

if(auto file = std::ifstream(filename); !file)
    throw std::runtime_error(std::strerror(errno));
else
{
    // use file here
}

कुछ लोग कोड को पसंद करते हैं ताकि एक फ़ंक्शन त्रुटि पर जल्दी से समाप्त हो जाए और अन्यथा प्रगति हो। यह मुहावरा शारीरिक तर्क को निरंतरता के तर्क से ऊपर रखता है जो कुछ लोगों को अधिक स्वाभाविक लग सकता है।


8

यह तार्किक घटनाओं के लिए विशेष रूप से उपयोगी है। इस उदाहरण पर विचार करें:

char op = '-';
if (op != '-' && op != '+' && op != '*' && op != '/') {
    std::cerr << "bad stuff\n";
}

थोड़ा मोटा लगता है। जब तक आप OR, ANDनकारात्मकताओं से बहुत परिचित हैं, तब तक आपको इस तर्क के बारे में सोचने और सोचने की आवश्यकता हो सकती है - जो आमतौर पर खराब डिजाइन है। if-initializationआप अभिव्यंजकता के साथ जोड़ सकते हैं।

char op = '-';
if (bool op_valid = (op == '-') || (op == '+') || (op == '*') || (op == '/'); !op_valid) {
    std::cerr << "bad stuff\n";
} 

नामित चर का फिर से उपयोग किया जा सकता ifहै। उदाहरण के लिए:

if (double distance = std::sqrt(a * a + b * b); distance < 0.5){
    std::cerr << distance << " is too small\n";
}

यह बहुत अच्छा है, विशेष रूप से यह देखते हुए कि चर scoped है और इसलिए बाद में अंतरिक्ष को प्रदूषित नहीं करता है।


2
मुझे एहसास हुआ कि यह व्यक्तिपरक है, लेकिन मैं अगर इनिशियलाइज़र के साथ अपने "रफ" संस्करण को पसंद करता हूं। मुझे यह पढ़ने और समझने में आसान लगता है।
फैबियो का कहना है कि मोनिका

@FabioTurati मुझे लगता है कि आप इससे बहुत परिचित हैं और दूसरा संस्करण नया है। लेकिन समय के साथ मुझे उम्मीद है कि इनिशियलाइज़र कुछ इसी तरह की रूपरेखा तैयार करेगा।
स्टैक डैनी

7

यह एक मौजूदा विशेषता का विस्तार है, जो मेरे अनुभव में पठनीयता को बढ़ाता है।

if (auto* ptr = get_something()) {
}

यहां हम दोनों वैरिएबल बनाते हैं ptrऔर हम इसे गैर-अशक्त होने के खिलाफ परीक्षण करते हैं। का दायरा ptrवहीं तक सीमित है जहां यह मान्य है। अपने आप को यह समझाना बहुत आसान है कि सभी उपयोग ptrमान्य हैं।

लेकिन क्या होगा अगर हम किसी ऐसी चीज के बारे में बात कर रहे हैं जो boolउस तरह से परिवर्तित नहीं होती है?

if (auto itr = find(bob)) {
}

यह काम नहीं करता है। लेकिन इस नई सुविधा के साथ हम कर सकते हैं:

if (auto itr = find(bob); itr != end()) {
}

एक खंड जोड़ें "जब यह इनिशियलाइज़ेशन मान्य है"।

संक्षेप में, यह हमें टोकन का एक सेट देता है, जिसका अर्थ है "कुछ अभिव्यक्ति को इनिशियलाइज़ करें, और जब यह मान्य हो, तो कुछ कोड करें। जब यह मान्य न हो, तो इसे छोड़ दें।"

C ++ 98 के बाद से पॉइंटर-टेस्ट ट्रिक करना मुहावरेदार है। एक बार जब आप इसे गले लगा लेते हैं, तो यह विस्तार स्वाभाविक है।

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