2009-10-04 54 views
23

Stroustrup के सी ++ प्रोग्रामिंग भाषा में एक चर आरंभ: विशेष संस्करण (3 एड), Stroustrup लिखते हैं कि घोषणा और नियंत्रण बयानों की सशर्त में चर का प्रारंभ न केवल है अनुमति दी, लेकिन प्रोत्साहित किया। वह लिखता है कि वह इसे प्रोत्साहित करता है क्योंकि यह चर के दायरे को केवल उस दायरे में कम कर देता है जिसके लिए उन्हें आवश्यकता होती है। तो इस तरह कुछ ...घोषणा और सी में एक सशर्त या नियंत्रण बयान ++

if ((int i = read(socket)) < 0) { 
    // handle error 
} 
else if (i > 0) { 
    // handle input 
} 
else { 
    return true; 
} 

... अच्छी प्रोग्रामिंग शैली और अभ्यास है। परिवर्तनीय i केवल if बयान के ब्लॉक के लिए मौजूद है जिसके लिए इसकी आवश्यकता है और फिर दायरे से बाहर हो जाता है।

हालांकि, प्रोग्रामिंग भाषा की यह विशेषता g ++ (संस्करण 4.3.3 उबंटू विशिष्ट संकलन) द्वारा समर्थित प्रतीत नहीं होती है, जो मेरे लिए आश्चर्यजनक है। शायद मैं सिर्फ एक झंडा के साथ जी ++ को बुला रहा हूं जो इसे बंद कर देता है (मैंने जो झंडे बुलाए हैं वे -g और -Wall हैं)। ++ निम्नलिखित संकलन त्रुटि देता है जब उन झंडे के साथ संकलन जी का मेरा संस्करण:

socket.cpp:130: error: expected primary-expression before ‘int’ 
socket.cpp:130: error: expected `)' before ‘int’ 

आगे अनुसंधान पर मुझे पता चला कि मैं एक संकलक है कि इस का समर्थन नहीं करता साथ केवल एक ही होने के लिए नहीं मालूम था। और this question में कुछ भ्रम प्रतीत होता था कि वास्तव में भाषा में सिंटैक्स मानक क्या था और इसके साथ संकलक किस संकलन करते थे।

तो सवाल यह है कि, कौन से कंपाइलर्स इस सुविधा का समर्थन करते हैं और संकलन के लिए किस झंडे को सेट करने की आवश्यकता है? क्या यह कुछ मानकों में होने का मुद्दा है, न कि दूसरों में?

इसके अलावा, जिज्ञासा से बाहर, क्या लोग आमतौर पर स्ट्रॉस्ट्रप से सहमत होते हैं कि यह अच्छी शैली है? या यह एक ऐसी स्थिति है जहां किसी भाषा के निर्माता को उसके सिर में एक विचार मिलता है जिसे आवश्यक रूप से भाषा के समुदाय द्वारा समर्थित नहीं किया जाता है?

+0

मुझे नहीं पता कि किस कंपाइलर का समर्थन है, लेकिन मैं व्यक्तिगत रूप से इस दृष्टिकोण का उपयोग करता हूं जब भी मैं ऐसा कुछ करता हूं जिसे चरम चर के रूप में उपयोग करने से परे चर की आवश्यकता नहीं होती है। वही सवाल हालांकि, क्या यह बुरा अभ्यास है? – Chezz

+0

एक और उदाहरण: http://stackoverflow.com/questions/1380135/can-you-evaluate-a-constructor-call-to-boolean-with-an-overloaded-bool/1380364#1380364 –

+1

मैं तर्क दूंगा कि पूरा ब्लॉक द्वारा स्कॉइंग वैरिएबल का विचार खराब अभ्यास है क्योंकि यह लंबी विधियों से बहस करता है। मैं बॉब मार्टिन के कट्टरपंथी दावों की सिफारिश करता हूं कि उनकी बेहद सहायक पुस्तक * स्वच्छ कोड * में लंबाई कार्य करें; विशेष रूप से, एक विधि वास्तव में एक से अधिक नियंत्रण संरचना नहीं होनी चाहिए। –

उत्तर

18

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

विशेष मामले में आप दिखाते हैं, ऐसा प्रतीत नहीं होता कि आप दुर्भाग्य से अनुपालन करने का कोई तरीका ढूंढ सकते हैं।

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


संपादित करें:

कहा जा रहा है, मैं इसे एक भी बयान में बहुत अधिक मिश्रण करने के लिए एक अच्छा अभ्यास नहीं मिल रहा है, और मुझे लगता है कि यह एक साझा राय है। यदि आप किसी चर के मान को प्रभावित करते हैं, तो इसे किसी अन्य अभिव्यक्ति में उपयोग करें, कोड दोनों भागों को अलग करके अधिक पठनीय और कम भ्रमित हो जाएगा।

तो बल्कि इस का उपयोग करने से:

int i; 
if((i = read(socket)) < 0) { 
    // handle error 
} 
else if(i > 0) { 
    // handle input 
} 
else { 
    return true; 
} 

मुझे लगता है कि पसंद करेंगे:

int i = read(socket); 
if(i < 0) { 
    // handle error 
} 
else if(i > 0) { 
    // handle input 
} 
else { 
    return true; 
} 
+1

दूसरे उदाहरण के लिए, "i" को एक चर के रूप में उपयोग न करें। कड़ाई से स्थानीय चर के अलावा किसी अन्य चीज़ के लिए, नाम को सार्थक बनाएं। –

4

मैं एक ऐसी ही problem हुई:

समस्या int घोषणा के आसपास कोष्ठक हो रहा है। यदि आप, उनके बिना काम और परीक्षण व्यक्त अर्थात

if (int i = read(socket)) { 

काम करना चाहिए कर सकते हैं यह काम करना चाहिए, लेकिन इसका मतलब है कि परीक्षण != 0 है, जो नहीं है तुम क्या चाहते।

11

मैं इसे एक अच्छा शैली जब संभवतः शून्य सूचक के साथ इस्तेमाल किया पर विचार करें:

if(CObj* p = GetOptionalValue()) { 
    //Do something with p 
} 

इस तरह पी घोषित किया जाता है कि क्या, यह एक वैध सूचक है। कोई खतरनाक सूचक पहुंच खतरे नहीं है।

दूसरी ओर कम से कम कुलपति में पर ++ यह केवल उपयोग समर्थित (यानी देखना हो काम सच है)

3

आप एक बूलियन अभिव्यक्ति के रूप में एक घोषणा का उपयोग कर सकते हैं, आप एक के बीच में एक घोषणा नहीं लगा सकेंगे अभिव्यक्ति। मैं यह सोचने में मदद नहीं कर सकता कि आप बजेर्ने क्या कह रहे हैं, गलत पढ़ रहे हैं।

तकनीक लूप के नियंत्रण चर के लिए अधिक उपयोगी और वांछनीय है, लेकिन इस उदाहरण में मेरा मानना ​​है कि बीमार सलाह दी जाती है और स्पष्टता नहीं देती है। और निश्चित रूप से यह काम नहीं करता है! ;)

if(<type> <identifier> = <initialiser>) // valid, but not that useful IMO 

if((<type> <identifier> = <initialiser>) <operator> <operand>) // not valid 

for(<type> <identifier> = <initialiser>; 
    <expression>; 
    <expression>) // valid and desirable 

अपने उदाहरण में आप एक सशर्त में दुष्प्रभावों के साथ एक समारोह है, जो IMO तुम वहाँ चर घोषित करने के बारे में क्या सोच सकते हैं की परवाह किए बिना एक बुरा विचार है कहा जाता है।

+1

एर, क्या आप इसे करने के द्वारा वैरिएबल में परिणाम 'पढ़ा (सॉकेट) <0' नहीं डालेंगे? – RedGlyph

+0

बिल्कुल; मैंने यही कहा - यह अर्थ बदलता है। बिंदु यह है कि यह संकलित करता है, एक सशर्त में एक चर घोषित किया जाता है, लेकिन अभिव्यक्ति के बीच में नहीं। कोष्ठक इसे अभिव्यक्ति के बीच में रखते हैं। वैधता अभिव्यक्ति अभिव्यक्ति के साथ एक घोषणा क्या है। – Clifford

+0

मेरा बुरा! क्षमा करें, मैंने आपकी व्याख्या को गलत तरीके से पढ़ा है :) – RedGlyph

6

मैं इन स्थितियों में जितना संभव हो सके कॉन्स का उपयोग करता हूं। अपने उदाहरण के बजाय, मुझे क्या करना होगा:

const int readResult = read(socket); 
if(readResult < 0) { 
    // handle error 
} 
else if(readResult > 0) 
{ 
    // handle input 
} 
else { 
    return true; 
} 

इसलिए हालांकि गुंजाइश निहित नहीं है, यह वास्तव में कोई फर्क नहीं पड़ता, क्योंकि चर परिवर्तित नहीं किया जा सकता है।

+0

मुझे यह पसंद है। (अब 15+ वर्णों के साथ) – jmucchiello

3

रेडग्लिफ़ और फेरुसियो ने जो कहा, उसे जोड़ना। हो सकता है कि हम अभी भी एक सशर्त कथन में घोषित करने के लिए इसके उपयोग को सीमित करने के लिए निम्न कार्य कर सकते हैं: वे C++ 17 इस फिक्सिंग कर रहे हैं

if(int x = read(socket)) //x != 0 
{ 
    if(x < 0) //handle error 
    {} 
    else //do work 
    {} 
} 
else //x == 0 
{ 
    return true; 
} 
+0

मुझे यह पसंद है, मैं इस तरह के बयान को पुन: व्यवस्थित करने के बावजूद नहीं था :) –

0

देख अन्य लोगों 'अच्छा जवाब की मदद के लिए आप हमेशा ब्रेसिज़ द्वारा चर का दायरा सीमित कर सकते हैं: सीधे प्रश्न से संबंधित नहीं जबकि

{  
    const int readResult = read(socket); 
    if(readResult < 0) { 
    // handle error 
    } 
    else if(readResult > 0) 
    { 
    // handle input 
    } 
    else { 
    return true; 
    } 
} 
0

, उदाहरण के सभी पहली बार त्रुटि हैंडलिंग डालें। चूंकि 3 मामले हैं (> 0 -> डेटा, == 0 -> कनेक्शन बंद और < 0 -> त्रुटि), इसका मतलब है कि नए डेटा प्राप्त करने का सबसे आम मामला दो परीक्षणों की आवश्यकता है। पहले 0 की जांच करने से लगभग आधा तक परीक्षण की अपेक्षित संख्या में कटौती होगी।दुर्भाग्य से "अगर (int x = read (सॉकेट))" व्हाइट_Pawn द्वारा दिए गए दृष्टिकोण को अभी भी डेटा के मामले के लिए 2 परीक्षण की आवश्यकता है, लेकिन सी ++ 17 प्रस्ताव का उपयोग पहले> 0 के लिए परीक्षण करने के लिए किया जा सकता है।

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