C ++ में सामान्य व्यवहार, सामान्य गलतियाँ [बंद]


35

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

मैं उन जवाबों का भी स्वागत करता हूं जो एक विशाल प्रदर्शन में कमी को इंगित करते हैं जहां यह आमतौर पर अपेक्षित नहीं होगा। मेरे प्रोफेसरों में से एक ने एक बार मुझे एलआर (1) पार्सर जनरेटर के बारे में बताया जिसका उदाहरण मैंने लिखा है:

आपने अनावश्यक विरासत और आभासीता के कुछ उदाहरणों का उपयोग किया है। वंशानुक्रम एक डिजाइन को और अधिक जटिल बनाता है (और RTTI (रन-टाइम टाइप इंफ़ेक्शन) सबसिस्टम की वजह से अक्षम), और इसलिए इसका उपयोग केवल वहीं किया जाना चाहिए जहाँ यह समझ में आता है, जैसे कि पार्स तालिका में क्रियाओं के लिए। क्योंकि आप टेम्पलेट्स का गहन उपयोग करते हैं, इसलिए आपको व्यावहारिक रूप से विरासत की आवश्यकता नहीं है। "


6
C / C ++ में आपके द्वारा की जाने वाली कुछ अधिक गलतियां ज्यादातर C विरासत की वजह से हैं ... अपरिभाषित व्यवहार, मैन्युअल मेमोरी प्रबंधन आदि पढ़ें। इसके अलावा, प्रोफेसर की सलाह फर्जी / गलत लगती है (मेरे लिए, जो नहीं है C ++ विशेषज्ञ) - टेम्पलेट तात्कालिकता को virtualकार्यों के लिए व्यवहार्य के साथ एक सामान्य वर्ग प्राप्त करना चाहिए , है ना?

8
आप या तो गलत याद कर रहे हैं कि आपके प्रोफेसर ने क्या कहा, या उसे कोई सुराग नहीं था कि वह किस बारे में बात कर रहा है। व्युत्पन्न वर्गों को आमतौर पर चीजों को देखने के लिए RTTI (AKA प्रतिबिंब) का उपयोग करने की आवश्यकता नहीं होती है। यदि वे आभासी तरीकों का उपयोग कर रहे हैं, तो कोड को प्रेषण के लिए एक व्यवहार्य खोज करने की आवश्यकता हो सकती है, लेकिन यह बहुत सारे प्रोसेसर पर एक एएसएम निर्देश का अनुवाद करता है। कैशिंग मुद्दों के कारण यह एक निश्चित राशि से चीजों को धीमा कर सकता है, लेकिन आप कभी भी ओवरहेड को किसी भी सबसे अधिक उपयोग किए जाने वाले मामलों के तहत नोटिस करने की संभावना नहीं रखते हैं। C ++ से बचने के लिए बहुत सारे अच्छे कारण हैं, लेकिन व्यवहार्य लुक उनमें से एक नहीं है।
मेसन व्हीलर

5
@ फेलिक्सडोमबेक: इतनी उदारता से और बोर्ड भर में लागू किया गया, कि आपके प्रोफेसर से बोली सिर्फ अज्ञानता का एक बड़ा हिस्सा दिखाता है। जब आपके डिज़ाइन को किसी प्रकार के रनटाइम बहुरूपता की आवश्यकता होती है, तो वर्चुअल फ़ंक्शंस का उपयोग करना अक्सर सबसे अच्छा विकल्प होता है; जब आपको इसकी आवश्यकता नहीं है, तो इसका उपयोग न करें: उदाहरण के लिए, आप सभी विधियों को आभासी होने की आवश्यकता नहीं है, क्योंकि आप व्युत्पन्न वर्ग का उपयोग करते हैं।
फ्रेड नर्क

5
@ मेसन व्हीलर: आरटीटीआई में प्रकार पर जानकारी शामिल है, यह निर्धारित करने में सक्षम होने के लिए पर्याप्त है कि क्या dynamic_castसफल होना चाहिए या नहीं, और कुछ अन्य चीजें, लेकिन प्रतिबिंब बहुत अधिक शामिल है, जिसमें सदस्य विशेषताओं या कार्यों पर जानकारी प्राप्त करने में सक्षम होना शामिल है, जो नहीं है C ++ में मौजूद है।
डेविड रोड्रिगेज -

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

जवाबों:


69

टॉर्वाल्ड्स अपने गधे के यहाँ बात कर रहे हैं।


ठीक है, वह अपने गधे से क्यों बात कर रहा है:

सबसे पहले, उसका शेख़ी वास्तव में कुछ भी नहीं है। यहां बहुत कम वास्तविक सामग्री है। एकमात्र कारण यह वास्तव में प्रसिद्ध है या हल्के से सम्मानित है क्योंकि यह लिनक्स भगवान द्वारा बनाया गया था। उसका मुख्य तर्क यह है कि C ++ बकवास है और वह C ++ लोगों को पेशाब करना पसंद करता है। वहाँ बिल्कुल कोई कारण नहीं है कि उस पर प्रतिक्रिया करने के लिए और जो कोई भी इसे एक उचित तर्क मानता है वह वैसे भी बातचीत से परे है।

जैसा कि उनके सबसे उद्देश्य अंक के रूप में क्या किया जा सकता है:

  • एसटीएल और बूस्ट बकवास है <- जो भी हो। तुम मुर्ख हो।
  • एसटीएल और बूस्ट में दर्द की अनंत मात्रा होती है <- हास्यास्पद। जाहिर है कि वह जानबूझकर अतिउत्साहित हो रहा है लेकिन फिर यहां उसका असली बयान क्या है? मुझे नहीं पता। जब आप स्पिरिट या किसी चीज़ में कंपाइलर उल्टी का कारण बनते हैं, तो मुद्दों का पता लगाने के लिए कुछ और अधिक कठिन होते हैं, लेकिन C कंस्ट्रक्शन जैसे void * के दुरुपयोग के कारण UB को डिबग करने की तुलना में अधिक या कम मुश्किल नहीं है।
  • C ++ द्वारा प्रोत्साहित किए गए सार मॉडल अक्षम हैं। <- क्या पसंद है? वह कभी विस्तार नहीं करता है, कभी भी इसका कोई उदाहरण नहीं देता है कि उसका क्या मतलब है, वह सिर्फ यह कहता है। BFD। चूँकि मैं यह नहीं बता सकता कि वह जिस बात का ज़िक्र कर रहा है, वह बयान को "खंडन" करने की कोशिश कर रही है। यह C bigots का एक सामान्य मंत्र है, लेकिन यह किसी भी अधिक समझ में आता है या समझदार नहीं है।
  • C ++ का सही उपयोग का अर्थ है कि आप अपने आप को C पहलुओं तक सीमित रखते हैं। <- वास्तव में वर्क सी + + कोड वहाँ ऐसा करता है इसलिए मुझे अभी भी पता नहीं है कि डब्ल्यूटीएफ वह किस बारे में बात कर रहा है।

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

सिर्फ इसलिए कि भगवान कहते हैं कि इसका मतलब यह नहीं है कि इसका कोई मतलब है या किसी और से गंभीरता से लिया जाना चाहिए अगर कुछ यादृच्छिक बोजो ने कहा। सच कहा जाए, तो भगवान सिर्फ एक और यादृच्छिक बोझा है।


वास्तविक सवाल का जवाब:

संभवतः सबसे खराब, और सबसे आम, खराब C ++ अभ्यास है, इसका इलाज सी की तरह करें। सी एपीआई के प्रिंटफ जैसे निरंतर कार्यों का उपयोग, (सी में भी बुरा माना जाता है), स्ट्रैटोक, आदि ... न केवल प्रदान की गई शक्ति का लाभ उठाने में विफल तंग प्रकार की प्रणाली द्वारा, वे "वास्तविक" सी ++ कोड के साथ बातचीत करने की कोशिश करते समय अनिवार्य रूप से आगे की जटिलताओं का नेतृत्व करते हैं। तो मूल रूप से, Torvalds क्या सलाह दे रहा है, इसके ठीक विपरीत करें।

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

यह नहीं कहना कि सी उतना अच्छा नहीं है। मैं निश्चित रूप से सी ++ की तरह बेहतर हूं। C प्रोग्रामर को C बेहतर पसंद है। खेल में व्यापार बंद और व्यक्तिपरक पसंद हैं। वहाँ भी गलत सूचना और FUD बहुत कुछ तैर रहा है। मैं कहूंगा कि C ++ के बारे में और अधिक FUD और गलत जानकारी तैर रही है लेकिन मैं इस संबंध में पक्षपाती हूं। उदाहरण के लिए, "ब्लोट" और "प्रदर्शन" समस्याएं C ++ माना जाता है कि वास्तव में ज्यादातर समय प्रमुख मुद्दे नहीं होते हैं और निश्चित रूप से वास्तविकता के अनुपात से बाहर उड़ा दिए जाते हैं।

जैसा कि आपके प्रोफेसर जिन मुद्दों का जिक्र कर रहे हैं, ये C ++ के लिए अद्वितीय नहीं हैं। OOP में (और सामान्य प्रोग्रामिंग में) आप वंशानुक्रम पर रचना को प्राथमिकता देना चाहते हैं। वंशानुक्रम सबसे मजबूत संभव युग्मन संबंध है जो सभी ओओ भाषाओं में मौजूद है। C ++ एक और जोड़ता है जो मजबूत है, दोस्ती। पॉलीमॉर्फिक इनहेरिटेंस का उपयोग अमूर्तताओं का प्रतिनिधित्व करने के लिए किया जाना चाहिए और "एक-एक" रिश्ते हैं, इसका उपयोग कभी भी पुन: उपयोग नहीं किया जाना चाहिए। यह दूसरी सबसे बड़ी गलती है जिसे आप C ++ में कर सकते हैं, और यह एक बहुत बड़ा है, लेकिन यह अद्वितीय भाषा से दूर है। आप C # या Java में अत्यधिक जटिल वंशानुक्रम संबंध भी बना सकते हैं, और उनकी समस्याएं भी बिल्कुल वैसी ही होंगी।


1
विडंबना, साथ ही 2007 के बाद, git ने केवल Linux के संस्करणों को चलाया। खैर, कोई भी प्रणाली जो यूनिक्स-समान थी। फिर से, परिस्थितियों को देखते हुए, जो कि सृजन की ओर ले गई, मैं निश्चित रूप से उसके खिलाफ नहीं हूँ।
क्रिस के

9
लिनुस के पास कोई भी अच्छा सी ++ प्रोग्रामर खोजने का कठिन समय है जो उसके लिए काम करना चाहते हैं। सोचता हूँ क्यों? मुझे लगता है कि यह सिर्फ एक चिकन और अंडे की समस्या है।
बो पर्सन

19

मैंने हमेशा सोचा है कि सी + + के खतरों को अनुभवहीन, सी द्वारा कक्षाओं के प्रोग्रामर के साथ अत्यधिक अतिरंजित किया गया था।

हां, C ++, Java जैसी किसी चीज़ से अधिक कठिन है, लेकिन यदि आप आधुनिक तकनीकों का उपयोग करके प्रोग्राम बनाते हैं, तो मजबूत प्रोग्राम लिखना बहुत आसान है। मैं ईमानदारी से C ++ में एक समय की प्रोग्रामिंग से ज्यादा मुश्किल नहीं हूं जितना कि मैं जावा जैसी भाषाओं में करता हूं, और मैं अक्सर खुद को कुछ C ++ एब्स्ट्रैक्ट जैसे टेम्प्लेट और RAII को याद करता हूं जब मैं अन्य भाषाओं में डिजाइन करता हूं।

कहा कि, C ++ में प्रोग्रामिंग के वर्षों के बाद भी, हर अब और फिर मैं वास्तव में एक बेवकूफ गलती करूंगा जो उच्च-स्तरीय भाषा में संभव नहीं होगा। C ++ में एक सामान्य नुकसान वस्तु जीवनकाल को नजरअंदाज कर रहा है: जावा और C # में आपको आमतौर पर ऑब्जेक्ट लाइफटाइम * के बारे में परवाह नहीं है, क्योंकि सभी ऑब्जेक्ट्स ढेर पर मौजूद हैं और वे आपके लिए एक जादुई कचरा संग्रहकर्ता द्वारा प्रबंधित हैं।

अब, आधुनिक C ++ में, आमतौर पर आपको ऑब्जेक्ट लाइफ-टाइम के बारे में अधिक ध्यान रखने की आवश्यकता नहीं होती है। आपके पास विध्वंसक और स्मार्ट पॉइंटर्स हैं जो आपके लिए वस्तुओं के जीवनकाल का प्रबंधन करते हैं। 99% समय, यह आश्चर्यजनक रूप से काम करता है। लेकिन हर अब और फिर, आप एक झूलने वाले सूचक (या संदर्भ) द्वारा खराब हो जाएंगे उदाहरण के लिए, अभी हाल ही में मेरे पास एक वस्तु थी (चलो इसे कॉल करें Foo) जिसमें एक आंतरिक संदर्भ चर था जो किसी अन्य वस्तु (चलो इसे कॉल करें Bar)। एक बिंदु पर, मैंने बेवकूफी से चीजों को व्यवस्थित किया, ताकि Barपहले गुंजाइश से बाहर हो गया Foo, फिर भी Fooविध्वंसक ने एक सदस्य समारोह को समाप्त कर दिया Bar। कहने की जरूरत नहीं है, चीजें अच्छी तरह से बाहर नहीं निकलीं।

अब, मैं वास्तव में इसके लिए C ++ को दोष नहीं दे सकता। यह मेरा अपना बुरा डिज़ाइन था, लेकिन इस तरह की बात उच्च स्तरीय, प्रबंधित भाषा में नहीं होगी। यहां तक ​​कि स्मार्ट पॉइंटर्स और पसंद के अनुसार, आपको कभी-कभी ऑब्जेक्ट लाइफ-टाइम के बारे में जागरूकता रखने की आवश्यकता होती है।


* यदि संसाधन प्रबंधित किया जा रहा है, तो यह मेमोरी है।


8
वास्तव में जावा और सी # में वस्तु जीवनकाल के बारे में परवाह करने के लिए कभी नहीं? उनकी GC स्मृति का ख्याल रखती है, लेकिन मेरे लिए RAII का केवल एक छोटा हिस्सा है; उदाहरण के लिए, उन विभिन्न "डिस्पोजेबल" इंटरफेसों को देखें जिनके पास भाषाएँ हैं।
फ्रेड नर्क

जावा / I लाइब्रेरी की असुविधाजनक डिजाइन को छोड़कर, ऑब्जेक्ट जीवनकाल के बारे में परवाह करना जावा में दुर्लभ होगा
dan04

आपका झूलना संदर्भ मुद्दा कुछ ऐसा है जिसे मैं हल करने की कोशिश में दिलचस्पी रखता हूं। मैंने अपने ब्लॉग पर उस दिशा के बारे में चर्चा शुरू की, जो मैं इसे हल करने के लिए नेतृत्व कर रहा हूं (पॉइंटर वादे)। मूल रूप से मुझे लगता है कि भाषा कुछ और स्मार्ट पॉइंटर्स का उपयोग कर सकती है। यदि आप रुचि रखते हैं तो उस चर्चा में भाग लें। किसी और के पास ऐसा कुछ नहीं है ... लेकिन अगर यह कुछ ऐसा है जिसे आप हल करना चाहते हैं ... मैं वास्तव में इस मुद्दे पर 10% से अधिक समय से चला रहा हूं।
एडवर्ड स्ट्रेंज

13

कोड में अंतर आमतौर पर भाषा की तुलना में प्रोग्रामर से अधिक संबंधित होता है। विशेष रूप से, एक अच्छा सी ++ प्रोग्रामर और एक सी प्रोग्रामर दोनों समान रूप से अच्छे (भले ही अलग-अलग) समाधान आएंगे। अब, सी एक सरल भाषा है (एक भाषा के रूप में) और इसका मतलब है कि कोड में वास्तव में क्या करता है इसमें कम सार और अधिक दृश्यता है।

उसके शेख़ी का एक हिस्सा (वह सी ++ के खिलाफ उसके शेख़ी के लिए जाना जाता है) इस तथ्य पर आधारित है कि अधिक लोग सी ++ पर ले जाएंगे, और कोड को वास्तव में समझने के बिना लिखेंगे कि कुछ सार क्या छिपाते हैं और गलत धारणा बनाते हैं।


3
std::vector<bool>प्रत्येक मूल्य को बदलने पर पुनरावृत्ति करने की लागत क्या है ? for ( std::vector<bool>::iterator it = v.begin(), end = v.end(); it != end; ++it ) { *it = !*it; }? क्या दूर में सार है *it = !*it;?
डेविड रोड्रिगेज -

2
हालाँकि, विशिष्ट भाषा में व्यापक रूप से गलतियों के रूप में की गई आलोचनाओं को उठाना अनुचित हो सकता है ...
फ्रेड नर्क

2
@ फ्रेड नर्क: std::vector<bool>एक अच्छी तरह से ज्ञात गलती है, लेकिन यह एक बहुत अच्छा उदाहरण है कि क्या चर्चा की जा रही है: सार अच्छा है, लेकिन आपको इस बात से सावधान रहना होगा कि वे क्या छिपाते हैं। यूजर कोड में भी यही होगा और होगा। शुरुआत के लिए, मैंने सी ++ और जावा दोनों लोगों को प्रवाह नियंत्रण करने के लिए अपवादों का उपयोग करते हुए देखा है, और कोड जो एक नेस्टिंग फ़ंक्शन कॉल की तरह दिखता है जो वास्तव में एक बेलआउट अपवाद लांचर है: के void endOperation();रूप में लागू किया गया throw EndOperation;। एक अच्छा प्रोग्रामर उन आश्चर्यजनक निर्माणों से बच जाएगा , लेकिन तथ्य यह है कि आप उन्हें पा सकते हैं।
डेविड रोड्रिग्ज - 21

5
Torvalds के बिंदुओं में से एक यह है कि: वह C ++ पर C चुनकर शुरुआती लोगों को दूर कर सकता है (अधिक C ++ शुरुआती लगता है) और C ++ अधिक जटिल होने के कारण एक स्टेटर लर्निंग कर्व होता है और एक कोने के मामले में ट्रिपिंग की अधिक संभावना होती है। ।
डेविड रॉड्रिग्ज - drieas

2
+1, यह वही है जो लिनस के बारे में शिकायत कर रहा है। वह C-C ++ के विरोधी के रूप में आता है, लेकिन वास्तव में ऐसा नहीं है। वह केवल विरोधी C ++ - प्रोग्रामर है।
ग्रेफेड

13

try/catchब्लॉक का अति प्रयोग ।

File file("some.txt");
try
{
  /**/

  file.close();
}
catch(std::exception const& e)
{
  file.close();
}

यह आमतौर पर जावा जैसी भाषाओं से उपजा है और लोग तर्क देंगे कि सी ++ में एक finalizeखंड का अभाव है ।

लेकिन यह कोड दो मुद्दों को प्रदर्शित करता है:

  • एक से fileपहले निर्माण करने की आवश्यकता है try/catch, क्योंकि आप वास्तव में closeएक फ़ाइल नहीं है जो अस्तित्व में नहीं है catch। यह "स्कोप लीक" की ओर जाता है जो fileबंद होने के बाद दिखाई देता है। आप एक ब्लॉक जोड़ सकते हैं लेकिन ...: /
  • यदि कोई आसपास आता है और दायरे returnके बीच में जोड़ देता है try, तो फ़ाइल बंद नहीं होती (यही कारण है कि लोग finalizeखंड की कमी के बारे में कुतिया हैं )

हालाँकि, C ++ में, हमारे पास इस समस्या से निपटने के बहुत अधिक कुशल तरीके हैं:

  • जावा के finalize
  • सी # के using
  • जाओ के defer

हमारे पास RAII है, जिसकी वास्तव में दिलचस्प संपत्ति सबसे अच्छी है SBRM(स्कोप्ड बाउंड रिसोर्स मैनेजमेंट)।

वर्ग को तैयार करने से ताकि उसका विध्वंसक संसाधनों को साफ कर सके, जो हमारे पास है, हम उसके प्रत्येक उपयोगकर्ता पर संसाधन के प्रबंधन का अधिकार नहीं रखते हैं!

यह वह विशेषता है जो मुझे किसी अन्य भाषा में याद आती है, और शायद वह है जो सबसे अधिक भूल गई है।

सच्चाई यह है कि try/catchलॉगिंग के बिना समाप्ति से बचने के लिए शीर्ष स्तर के अलावा, सी ++ में भी शायद ही कोई ब्लॉक लिखने की आवश्यकता है ।


1
मुझे नहीं लगता कि यह जावा का उतना ही प्रभाव है जितना कि यह सी (आप सीधे fopenऔर fcloseयहां स्थानापन्न कर सकते हैं।) RAII यहां चीजों को करने का "उचित" तरीका है, लेकिन यह उन लोगों के लिए असुविधाजनक है जो C ++ से C पुस्तकालयों का उपयोग करना चाहते हैं। ।
dan04

इस प्रकार के उत्तर के लिए, सही समाधान का उदाहरण प्रदान करना उचित होगा।
क्लॉस जोर्जेंसन

@ ClausJørgensen: ठीक है, दुर्भाग्य से समाधान वास्तव में "दिखावटी" नहीं है क्योंकि इसमें सिर्फ File file("some.txt");और सिर्फ यही शामिल है (नहीं open, नहीं close, नहीं try...)
मैथ्यू एम।

D का आरएआईआई भी है
डेमी

@ डेमेट्री: मैं डी से बहुत परिचित नहीं हूं, क्या आप बता सकते हैं कि आरएआई ने गारबेज कलेक्शन के साथ कैसे बातचीत की? मुझे पता है कि पाइथन में आप एक "डिनिट" विधि लिख सकते हैं, हालांकि दस्तावेज़ीकरण चेतावनी देता है कि संदर्भ के चक्र के मामले में कुछ वस्तुओं को उनकी डिनिट विधि नहीं कहा जाएगा।
Matthieu M.

9

एक सामान्य त्रुटि जो आपके मानदंड को फिट करती है, यह समझ में नहीं आ रहा है कि आपकी कक्षा में आवंटित मेमोरी से निपटने के दौरान निर्माणकर्ता कैसे काम करते हैं। मैंने जितनी बार क्रैश या मेमोरी लीक को ठीक करने में खर्च किया है, उसकी गिनती खो दी है क्योंकि एक 'noob' ने अपनी वस्तुओं को एक मानचित्र या वेक्टर में डाल दिया और कॉपी कंस्ट्रक्टर और डिस्ट्रक्टर्स को ठीक से नहीं लिखा।

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


1
मुझे लगता है कि सी ++ के साथ समस्या यह है कि अपने आप को पैर में गोली मारना बहुत आसान है। ज़रूर, वहाँ अच्छे C ++ प्रोग्रामर हैं, C ++ में बहुत सारे अच्छे सॉफ़्टवेयर लिखे गए हैं। लेकिन एक अच्छा C ++ डेवलपर बनना बहुत मुश्किल है। स्कॉट मेयर्स 'कुशल सी ++' श्रृंखला से पता चलता है कि भाषा की कितनी सूक्ष्मता है।
मार्को मस्टैपिक

मैं सहमत हूँ। हालांकि समस्या का एक हिस्सा यह है कि C ++ प्रोग्रामर का एक बहुत (बहुमत) उन्हें लगता है कि वे जानते हैं कि वे क्या कर रहे हैं जब वे स्पष्ट रूप से नहीं करते हैं। क्या आपका मतलब "प्रभावी C ++" था?
हेनरी

कम से कम यह C ++ 0x में कॉपी / मूव ऑपरेशंस की निहित पीढ़ी पर नए बल्कि प्रतिबंधात्मक नियमों के साथ बेहतर हो रहा है। नियम के तीन उल्लंघनों के कई मामलों में कॉपी संचालन की अंतर्निहित पीढ़ी को हटा दिया जा रहा है और चेतावनी का उत्पादन करना चाहिए।
बेच दें

6

C ++ कई प्रकार की सुविधाओं और प्रोग्रामिंग शैलियों की अनुमति देता है, लेकिन इसका मतलब यह नहीं है कि ये वास्तव में C ++ का उपयोग करने के लिए अच्छे तरीके हैं। और वास्तव में, सी ++ का गलत तरीके से उपयोग करना अविश्वसनीय रूप से आसान है।

इसे ठीक से सीखना और समझना होगा , बस (या किसी अन्य भाषा का उपयोग करने की तरह इसका उपयोग करके सीखना) अक्षम और त्रुटि-प्रवण कोड का नेतृत्व करेगा।


4

खैर ... शुरुआत के लिए आप C ++ FAQ Lite पढ़ सकते हैं

फिर, कई लोगों ने C ++ की पेचीदगियों के बारे में किताबें लिखने वाले करियर का निर्माण किया है:

हर्ब सटर और स्कॉट मेयर्स अर्थात्।

के रूप में Torvalds 'शेख़ी कमी पदार्थ के लिए ... लोगों पर आते हैं, गंभीरता से: कोई अन्य भाषा वहाँ इतनी स्याही भाषा की बारीकियों से निपटने पर गिरा दिया गया है। आपकी पायथन और रूबी और जावा पुस्तकें सभी एप्लिकेशन लिखने पर ध्यान केंद्रित करती हैं ... आपकी सी ++ पुस्तकें मूर्खतापूर्ण भाषा सुविधाओं / युक्तियों / जाल पर केंद्रित हैं।


1
हम्म ... javapuzzlers.com , jimbrooks.org/web/python/#Pitashes । मैं कहता हूँ कि त्वरित C ​​++ (एक उदाहरण के लिए) इन पर कोड लिखने के तरीके पर अधिक ध्यान केंद्रित करता है ...
जैरी कॉफिन

1
आप उन संसाधनों के उदाहरणों के एक जोड़े को लेकर आए हैं जो अपनी-अपनी भाषाओं में किनारे के मामलों को इंगित करते हैं; चीजें हैं जो अजीब लग रही है और आप काफी यकीन है कि वे कैसे काम करते हैं (हालांकि अजगर सूची सामान करीब है) नहीं कर रहे हैं ... सी ++ एक पूरी है उद्योग चीजें हैं जो उनका कहना है देखने के लिए पूरी तरह से वैध है कि तरीके से व्यवहार आपको उम्मीद नहीं है।
लाल-गंदगी

3

बहुत भारी टेम्प्लेटिंग के परिणामस्वरूप पहले कीड़े नहीं हो सकते हैं। जैसे-जैसे समय बीत रहा है, वैसे-वैसे लोगों को उस कोड को संशोधित करने की आवश्यकता होगी, और उन्हें एक विशाल टेम्पलेट को समझने में कठिन समय होगा। जब कीड़े प्रवेश करते हैं - गलतफहमी का कारण बनता है "यह संकलित करता है और चलाता है" टिप्पणियां, जो अक्सर लगभग-लेकिन-नहीं-काफी-सही कोड की ओर ले जाती हैं।

आम तौर पर अगर मैं खुद को तीन-स्तरीय गहरे सामान्य टेम्पलेट करते हुए देखता हूं, तो मैं रुक जाता हूं और सोचता हूं कि इसे कैसे कम किया जा सकता है। अक्सर समस्या को कार्यों या कक्षाओं को निकालने से हल किया जाता है।


8
बदलती आवश्यकताओं के चेहरे में जटिल कोड बनाए रखना हमेशा बहुत प्रयास के बिना बग का कारण बनता है, विशेष रूप से वहाँ के टेम्पलेट्स के बारे में कुछ भी विशेष नहीं है।
फ्रेड नर्क

2

चेतावनी: यह लगभग एक उत्तर के रूप में बात का एक समालोचक के रूप में नहीं है कि "उपयोगकर्ता unkown" उसके उत्तर में जुड़ा हुआ है।

उनका पहला मुख्य बिंदु (माना जाता है) "कभी बदलते मानक" है। हकीकत में, वह जो उदाहरण देता है वह सभी मानक से पहले C ++ में बदलाव से संबंधित है । 1998 के बाद से (जब पहले C ++ मानक को अंतिम रूप दिया गया था) भाषा में परिवर्तन काफी कम रहे हैं - वास्तव में, कई लोग तर्क देंगे कि असली समस्या यह है कि अधिक बदलाव किए जाने चाहिए थे। मैं यथोचित निश्चित हूं कि सभी कोड जो मूल C ++ मानक के अनुरूप हैं, अभी भी वर्तमान मानक के अनुरूप हैं। हालांकि यह कुछ हद तक कम है, जब तक कि कुछ जल्दी (और काफी अप्रत्याशित रूप से) नहीं बदलता है, वही आगामी सी ++ मानक के साथ भी बहुत सही होगा (सैद्धांतिक रूप से, सभी कोड जो उपयोग किए गए हैंexportटूट जाएगा, लेकिन वस्तुतः कोई भी मौजूद नहीं है; व्यावहारिक दृष्टिकोण से यह एक मुद्दा नहीं है)। मैं कुछ अन्य भाषाओं के बारे में सोच सकता हूं, OSes (या कंप्यूटर से संबंधित कुछ भी) जो इस तरह का दावा कर सकते हैं।

वह फिर "कभी बदलती शैलियों" में चला जाता है। फिर से, उनके अधिकांश अंक बकवास के बहुत करीब हैं। वह for (int i=0; i<n;i++)"पुरानी और पर्दाफाश" और for (int i(0); i!=n;++i)"नई हॉटनेस" के रूप में चिह्नित करने की कोशिश करता है । वास्तविकता यह है कि जबकि ऐसे प्रकार हैं जिनके लिए इस तरह के परिवर्तन समझ में आ सकते हैं int, इसके लिए , इससे कोई फर्क नहीं पड़ता है - और यहां तक ​​कि जब आप कुछ हासिल कर सकते हैं, तो यह अच्छा या सही कोड लिखने के लिए शायद ही आवश्यक हो। यहां तक ​​कि बहुत अच्छे से, वह एक पहाड़ को मोलेहिल से बना रहा है।

उनका अगला दावा है कि C ++ "गलत दिशा में अनुकूलन" है - विशेष रूप से, जबकि वह स्वीकार करते हैं कि अच्छी पुस्तकालयों का उपयोग करना आसान है, उनका दावा है कि C ++ "अच्छी पुस्तकालयों को लिखना लगभग असंभव बना देता है।" यहां, मेरा मानना ​​है कि उनकी सबसे बुनियादी गलतियों में से एक है। वास्तव में, लगभग किसी भी भाषा के लिए अच्छी लाइब्रेरी लिखना बेहद मुश्किल है। नंगे न्यूनतम पर, एक अच्छी लाइब्रेरी लिखने के लिए कुछ समस्या डोमेन को इतनी अच्छी तरह से समझने की आवश्यकता होती है कि आपका कोड उस डोमेन में (या संबंधित) संभावित अनुप्रयोगों की भीड़ के लिए काम करता है। ज्यादातर सी ++ वास्तव में क्या करता है "बार को बढ़ाएं" - यह देखने के बाद कि पुस्तकालय कितना बेहतर हो सकता है, लोग शायद ही कभी वापस जाने के लिए तैयार हों, जिस तरह का ड्रैक उनके पास है अन्यथा नहीं।वास्तव में अच्छे कोडर काफी कुछ पुस्तकालय लिखते हैं, जिसे तब "आसानी से, जैसा कि वह स्वीकार करता है" का उपयोग "बाकी हम" द्वारा किया जा सकता है। यह वास्तव में एक मामला है जहां "यह बग नहीं है, यह एक विशेषता है।"

मैं क्रम में हर बिंदु को हिट करने की कोशिश नहीं करूंगा (जो पृष्ठों को ले जाएगा), लेकिन सीधे अपने समापन बिंदु पर छोड़ दें। उन्होंने बज़्ने को यह कहते हुए उद्धृत किया: "पूरे प्रोग्राम ऑप्टिमाइज़ेशन का उपयोग अप्रयुक्त आभासी फ़ंक्शन तालिकाओं और आरटीटीआई डेटा को खत्म करने के लिए किया जा सकता है। इस तरह के विश्लेषण अपेक्षाकृत छोटे कार्यक्रमों के लिए विशेष रूप से उपयुक्त हैं जो गतिशील लिंकिंग का उपयोग नहीं करते हैं।"

उन्होंने एक असमर्थित दावा करते हुए कहा कि "यह वास्तव में एक कठिन समस्या है", यहाँ तक कि इसे रोकने की समस्या से तुलना करने पर भी यह आलोचना करता है। हकीकत में, यह कुछ भी नहीं है - वास्तव में, लिंकर को Zortech C ++ ( MS-DOS के लिए बहुत पहले C ++ कंपाइलर, 1980 में वापस) के साथ शामिल किया गया था। यह सच है कि यह निश्चित होना मुश्किल है कि संभवतः हर-एक्सटर्नल डेटा को समाप्त कर दिया गया है, लेकिन एक सुंदर निष्पक्ष काम करने के लिए पूरी तरह से उचित है।

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

अंत में, यह सच है कि इस शेख़ी में लिनुस की मूर्खता की तुलना में थोड़ा अधिक पदार्थ है - लेकिन यह वास्तव में बेहोश प्रशंसा के साथ यह नुकसान दे रहा है कि यह हकदार है।


1

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

कुछ प्रदर्शन हिट्स जो मैंने आमतौर पर देखे हैं, वे एसटीएल की जादुई मेमोरी आवंटन के कारण हैं (हाँ, आप आवंटनकर्ता को बदल सकते हैं, लेकिन कौन करता है जब वह सी ++ के साथ शुरू होता है?)। आप आमतौर पर C ++ विशेषज्ञों द्वारा तर्क सुनते हैं कि वैक्टर और सरणियाँ समान प्रदर्शन प्रदान करते हैं, क्योंकि वैक्टर आंतरिक रूप से सरणियों का उपयोग करते हैं और अमूर्त सुपर कुशल है। मैंने इसे वेक्टर एक्सेस और मौजूदा मूल्यों को संशोधित करने के अभ्यास में सही पाया है। लेकिन वैक्टर की एक नई प्रविष्टि, निर्माण और विनाश को जोड़ने के लिए सही नहीं है। ग्राफ्ट ने दिखाया कि किसी अनुप्रयोग के लिए संचयी रूप से 25% समय वेक्टर कंस्ट्रक्टर्स, डिस्ट्रक्टर्स, मेमोव (नए तत्व जोड़ने के लिए संपूर्ण वेक्टर के स्थानांतरण के लिए) और अन्य अतिभारित वेक्टर ऑपरेटरों (जैसे ++) में बिताया गया था।

एक ही आवेदन में, कुछ के वेक्टर का इस्तेमाल किया गया था, जो कि कुछ को दर्शाता है। ऐसा कुछ भी नहीं था, जिसमें कुछ भी नहीं था। फिर भी एक सूची के बजाय एक वेक्टर का उपयोग किया गया था। वेक्टर का उपयोग किस कारण किया गया था? क्योंकि मूल कोडर वैक्टर के सिंटैक्स की तरह सरणी से परिचित था और सूचियों के लिए आवश्यक पुनरावृत्तियों से बहुत परिचित नहीं था (हाँ वह एक सी पृष्ठभूमि से है)। यह साबित करने के लिए जाता है कि सी ++ को सही पाने के लिए विशेषज्ञों से बहुत सारे मार्गदर्शन की आवश्यकता होती है। C पूरी तरह से अमूर्तता के साथ इतने कम बुनियादी निर्माण प्रदान करता है, कि आप इसे C ++ की तुलना में बहुत आसान बना सकते हैं।


0

हालांकि मुझे लिनुस थोर्वाल्ड्स पसंद है, यह शेख़ी पदार्थ के बिना है - सिर्फ एक शेख़ी।

यदि आप एक प्रतिस्थापित शेख़ी देखना पसंद करते हैं, तो यहां एक है: "क्यों सी ++ पर्यावरण के लिए बुरा है, ग्लोबल वार्मिंग का कारण बनता है और पिल्लों को मारता है" http://chaosradio.ccc.de/camp2007_m4v_1951/ अतिरिक्त सामग्री: http: // www .fefe.de / c ++ /

एक मनोरंजक बात, इहो


0

स्रोत कोड स्तर पर एसटीएल और बूस्ट पोर्टेबल हैं। मुझे लगता है कि लिनुस जिस बारे में बात कर रहा है वह यह है कि सी ++ में एबीआई (एप्लिकेशन बाइनरी इंटरफ़ेस) का अभाव है। तो आपको उन सभी पुस्तकालयों को संकलित करने की आवश्यकता है जिनके साथ आप संकलित करते हैं, एक ही संकलक संस्करण के साथ और एक ही स्विच के साथ, या फिर स्वयं को dll सीमाओं पर C ABI तक सीमित करें। मुझे यह भी पता है कि annyoing .. लेकिन जब तक आप 3rd पार्टी लाइब्रेरी नहीं बना रहे हैं, आपको अपने बिल्ड वातावरण पर नियंत्रण रखने में सक्षम होना चाहिए। मुझे लगता है कि सी एबीआई के लिए खुद को सीमित करना परेशानी के लायक नहीं है। कंपाइलरों को बदलते समय या कंपाइलर स्विच को बदलते समय सभी पुस्तकालयों के पुनर्निर्माण की समस्या के कारण तार, वैक्टर और स्मार्ट पॉइंटर्स को एक डीएल से दूसरे पर ले जाने में सक्षम होने की सुविधा है। मेरे द्वारा पालन किए जाने वाले सुनहरे नियम हैं:

इंटरफ़ेस का पुन: उपयोग करने के लिए, कार्यान्वयन नहीं

- विरासत पर अधिक एकत्रीकरण

-जहां सदस्य विधियों के लिए संभव मुक्त कार्य करता है

-अपने कोड को जोरदार अपवाद को सुरक्षित बनाने के लिए रेलवे RAII मुहावरे का उपयोग करता है। ट्राई कैच से बचें।

स्मार्ट संकेत का उपयोग करें, नग्न (प्रसिद्ध) संकेत से बचें

-प्राप्त शब्दार्थ शब्दार्थ को संदर्भित करना

पहिया को सुदृढ़ न करें, stl का उपयोग करें और बढ़ावा दें

निजी और / या एक संकलक फ़ायरवॉल प्रदान करने के लिए Pimpl मुहावरे का उपयोग करें


-6

;कम से कम वीसी के कुछ संस्करणों में एक क्लैस घोषणा के अंत में एक फाइनल नहीं डाल रहा है ।


4
यह शायद शुरुआती लोगों के लिए एक बहुत ही सामान्य गलती है (जैसा कि अभी भी बुनियादी वाक्यविन्यास सीखने वाले किसी व्यक्ति के लिए लगभग कुछ भी है), लेकिन क्या कई ऐसे हैं जो खुद को सक्षम कहेंगे और फिर भी इस गलती को ध्यान देने योग्य पाएंगे?
फ्रेड नर्क

1
इसे सिर्फ इसलिए लिखा क्योंकि संकलक ने आपको एक त्रुटि दी जिसका अर्धविराम की कमी से कोई लेना-देना नहीं था।
मार्को मस्टैपिक

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