क्यों "नाम स्थान std का उपयोग कर रहे हैं;" बुरा अभ्यास माना जाता है?


2639

मुझे दूसरों द्वारा बताया गया है कि using namespace std;कोड में लिखना गलत है, और मुझे इसका उपयोग करना चाहिए std::coutऔर std::cinइसके बजाय सीधे।

क्यों using namespace std;एक बुरी प्रथा मानी जाती है? क्या यह अक्षम्य है या यह अस्पष्ट चर घोषित करने का जोखिम रखता है (चर जो नाम में एक समारोह के रूप में एक ही नाम साझा करते हैं std)? क्या यह प्रदर्शन को प्रभावित करता है?


512
मत भूलो कि आप क्या कर सकते हैं: "std का उपयोग कर :: cout?" जिसका अर्थ है कि आपको std :: cout टाइप नहीं करना है, लेकिन एक ही समय में पूरे std नेमस्पेस में नहीं लाना है।
बिल

2
@a भुगतान किया गया nerd google-styleguide.googlecode.com/svn/trunk/… लिंक अब काम नहीं करता है। नए लिंक की तरह दिखता है google.github.io/styleguide/cppguide.html#Other_C+_Features
MCG

64
हेडर फ़ाइलों में फ़ाइल स्कोप पर 'नेमस्पेस std' का उपयोग करना विशेष रूप से बुरा है। सभी शामिल होने के बाद फ़ाइल स्कोप पर स्रोत फ़ाइलों (* .cpp) में इसका उपयोग करना उतना बुरा नहीं है, क्योंकि इसका प्रभाव एकल अनुवाद इकाई तक सीमित है। यहां तक ​​कि कम समस्याग्रस्त इसे कार्यों या कक्षाओं के अंदर उपयोग कर रहा है, क्योंकि इसका प्रभाव फ़ंक्शन या वर्ग दायरे तक सीमित है।
श-

5
मैं निर्देशन का उपयोग करने के लिए हतोत्साहित करना चाहूंगा std::literals::chrono_literals, लेकिन विशिष्ट नामस्थान जैसे Poco::Data:Keywords, Poco::Unitsऔर सामान जो कि शाब्दिक या पठनीयता की चाल से निपटेंगे। जब भी यह शीर्ष लेख या कार्यान्वयन फ़ाइलों में होता है। यह एक ऐसा कार्यक्षेत्र हो सकता है, जिसका मैं अनुमान लगाता हूं, लेकिन शाब्दिक और सामान के अलावा, यह उपयोगी नहीं है।
लुडोविक ज़ेनोहेट लैगौर्डेट

7
@ जॉन: यह विशेष रूप से नामस्थान एसटीडी के साथ कुछ नहीं करना है। मेरा जोर "हेडर फ़ाइलों में फ़ाइल स्कोप पर" होने पर था। इसे एक सलाह के रूप में रखने के लिए: हेडर फ़ाइलों में फ़ाइल स्कोप पर "नेमस्पेस" (एसटीडी या अन्य) का उपयोग न करें। कार्यान्वयन फ़ाइलों में इसका उपयोग करना ठीक है। अस्पष्टता के लिए क्षमा करें।
sh-

जवाबों:


2229

यह प्रदर्शन से संबंधित नहीं है। लेकिन इस पर विचार करें: आप फू और बार नामक दो पुस्तकालयों का उपयोग कर रहे हैं:

using namespace foo;
using namespace bar;

सब कुछ ठीक काम करता है, और आप Blah()फू से और Quux()बार से समस्याओं के बिना कॉल कर सकते हैं । लेकिन एक दिन आप फू 2.0 के नए संस्करण में अपग्रेड करते हैं, जो अब एक फ़ंक्शन प्रदान करता है जिसे कहा जाता है Quux()। अब आपको एक संघर्ष मिल गया है: फू 2.0 और बार दोनों Quux()आपके वैश्विक नामस्थान में आयात करते हैं। यह ठीक करने के लिए कुछ प्रयास करने जा रहा है, खासकर अगर फ़ंक्शन मापदंडों का मिलान होता है।

यदि आपने उपयोग किया होता foo::Blah()और bar::Quux(), तो परिचय foo::Quux()एक गैर-घटना होता।


435
मैंने हमेशा पायथन के "आयात big_honkin_name को bhn" के रूप में पसंद किया है, इसलिए आप केवल "big_honkin_name.something" के बजाय "bhn.something" का उपयोग कर सकते हैं - वास्तव में टाइपिंग में कटौती करता है। क्या C ++ में ऐसा कुछ है?
पैक्सडिब्लो

764
@ पैक्स नामस्थान io = बढ़ावा :: फाइलसिस्टम;
आरा

152
मुझे लगता है कि यह "कुछ प्रयास को ठीक करने के लिए" कहने के लिए चीजों पर काबू पा रहा है। आपके पास नए foo का कोई उदाहरण नहीं होगा :: Quux इसलिए बार के साथ अपने सभी वर्तमान उपयोगों का खंडन करें :: Quux।
MattyT

289
क्या कोई समझदार व्यक्ति उन प्रकारों के साथ एक पुस्तकालय बनाएगा, जिनका अयोग्य नाम एसटीडी प्रकारों से टकराता है?
एरिकक्लेन

94
@ टोमा: के साथ समस्या #defineयह है कि यह खुद को नाम स्थान तक सीमित नहीं करता है, लेकिन पूरे कोड आधार पर ट्राम । एक नाम स्थान का उपनाम जो आप चाहते हैं।
sbi

1390

मैं ग्रेग द्वारा लिखी गई हर बात से सहमत हूं , लेकिन मैं जोड़ना चाहूंगा: ग्रेग ने कहा कि इससे भी बदतर हो सकता है!

लाइब्रेरी फू 2.0 एक फ़ंक्शन पेश कर सकता है Quux(), जो कि आपके कुछ कॉलों के लिए वर्षों से बुलाए गए कोड की Quux()तुलना में एक बेहतर ढंग से बेहतर मैच है bar::Quux()। फिर आपका कोड अभी भी संकलित है , लेकिन यह चुपचाप गलत फ़ंक्शन को कॉल करता है करता है और भगवान-जानता है-क्या। यह उतना ही बुरा है जितना कि चीजें मिल सकती हैं।

ध्यान रखें कि stdनाम स्थान पहचानकर्ता के टन, जिनमें से कई हैं बहुत आम लोगों (लगता है list, sort, string,iterator , भी, आदि) जो बहुत संभावना है अन्य कोड में प्रदर्शित करने के।

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


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

एक दशक में, उस परियोजना में कोड की कई मिलियन लाइनें बढ़ीं। चूँकि ये चर्चाएँ बार-बार उठती हैं, मैं एक बार उत्सुक usingथा कि परियोजना में वास्तव में (अनुमति) फ़ंक्शन-स्कोप का कितनी बार उपयोग किया गया था। मैं इसके लिए स्रोत तैयार करता हूं और केवल एक या दो दर्जन स्थानों पर पाया गया जहां इसका उपयोग किया गया था। मेरे लिए यह इंगित करता है कि, एक बार आजमाए जाने के बाद, डेवलपर्स std::को हर 100 kLoC पर एक बार भी निर्देशन का उपयोग करने के लिए पर्याप्त दर्दनाक नहीं लगता है , जहां इसे इस्तेमाल करने की अनुमति दी गई थी।


नीचे की रेखा: स्पष्ट रूप से सब कुछ उपसर्ग करने से कोई नुकसान नहीं होता है, इसका बहुत कम उपयोग होता है और इसका उद्देश्य लाभ होता है। विशेष रूप से, यह संकलक और मानव पाठकों द्वारा व्याख्या करने के लिए कोड को आसान बनाता है - और कोड लिखते समय शायद यह मुख्य लक्ष्य होना चाहिए।


140
यह कोड की घनत्व को काफी नुकसान पहुंचाता है जिसे आप एक ही लाइन में पैक कर सकते हैं। आप अपने कोड को बहुत लंबे-घुमावदार तरीके से लिखते हैं; जो पठनीयता को कम करता है। व्यक्तिगत रूप से, मुझे लगता है कि कम (लेकिन बहुत कम नहीं) कोड अधिक पठनीय हो जाता है (क्योंकि पढ़ने के लिए कम सामान है, और कम सामान के बारे में विचलित होने के लिए)।
रयान

91
लगता है कि आप पुराने दिनों से पहले याद किया C ++ में एक मानक stringवर्ग था, और प्रतीत होता है कि प्रत्येक पुस्तकालय का अपना था। आपको बताता हूं: हम अपना कोड लिखते रहेंगे std::, और grep -v std:: | vimजब आप इसे ब्राउज़ कर रहे हों, तो आप हमारे कोड को चला सकते हैं। या आप अपने संपादक को सिखा सकते हैं std::जो एक कीवर्ड है जिसे पृष्ठभूमि के रंग के समान रंग दिया जाना है। जो कुछ भी काम करता है।
माइक डेनिमोन

79
मुझे नहीं लगता कि std::यह हानिकारक है। यह बहुत ही महत्वपूर्ण जानकारी प्रदान करता है (अर्थात् "जो भी आता है वह मानक पुस्तकालय का हिस्सा है", और यह अभी भी एक बहुत छोटा और कॉम्पैक्ट उपसर्ग है। ज्यादातर समय, यह कोई समस्या नहीं है। कभी-कभी, आपके पास कोड की कुछ लाइनें होती हैं। जहाँ आपको stdनामस्थान में विशिष्ट प्रतीकों का उल्लेख करने की आवश्यकता है , और फिर usingउस विशेष क्षेत्र में एक बयान समस्या को अच्छी तरह से हल करता है। लेकिन सामान्य स्थिति में, यह शोर नहीं है, यह अस्पष्टताओं को दूर करने के अलावा मूल्यवान जानकारी भी देता है।
jalf

146
जब भी मैं देखता हूं std::, मुझे पता है कि इसके std::बारे में सोचने के बिना होने वाला है। तो मैं देख रहा हूँ stringया listया mapखुद से, मैं थोड़ा आश्चर्य है।
मतीन उलहाक

67
@LieRyan फिर कुछ भी नामकरण के बिना एक ज्यामिति पुस्तकालय लिखने के लिए शुभकामनाएँ vector, transformया distance। और वे मानक पुस्तकालय में उपयोग किए जाने वाले कई बहुत सामान्य नामों के उदाहरण हैं । उन्हें डर से बाहर न इस्तेमाल करने का सुझाव देना या नाम स्थान सुविधा का पक्षपाती विचार जो C ++ का अभिन्न अंग है, बल्कि प्रति-उत्पादक है।
ईसाई रौ

419

using namespaceअपनी कक्षाओं की हेडर फ़ाइलों में डालने के साथ समस्या यह है कि यह किसी को भी मजबूर करता है जो आपकी कक्षाओं (अपनी हेडर फ़ाइलों को शामिल करके) का उपयोग करने के लिए भी उन अन्य नामस्थानों का 'उपयोग' कर रहा है (यानी सब कुछ देखकर)।

हालाँकि, आप बेझिझक अपने (निजी) * .cpp फ़ाइलों में एक स्टेटमेंट का उपयोग कर सकते हैं।


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

उपयोग-निर्देश विरासत सी ++ कोड के लिए और नामस्थानों में संक्रमण को कम करने के लिए मौजूद है, लेकिन आपको संभवतः इसका उपयोग नियमित रूप से नहीं करना चाहिए, कम से कम आपके नए सी ++ कोड में नहीं।

एफएक्यू दो विकल्पों का सुझाव देता है:

  • एक का उपयोग करते हुए घोषणा:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • बस टाइपिंग एसटीडी ::

    std::cout << "Values:";

1
बेशक, आपको वैश्विक कॉट की स्थिति को कभी भी ग्रहण नहीं करना चाहिए, ऐसा न हो कि किसी ने std: cout << std :: hex और std करने में विफल रहा हो :: Restore_cout_state बाद में। लेकिन वह एक पूरी तरह से अन्य मोटा है।
9

233

मैं हाल ही में विजुअल स्टूडियो 2010 के बारे में एक शिकायत में भाग गया । यह पता चला कि बहुत सारे स्रोत फ़ाइलों में ये दो लाइनें थीं:

using namespace std;
using namespace boost;

बहुत सारे बूस्ट फीचर्स C ++ 0x स्टैंडर्ड में जा रहे हैं, और Visual Studio 2010 में C ++ 0x फीचर्स बहुत सारे हैं, इसलिए अचानक ये प्रोग्राम कंप्लीट नहीं हो रहे थे।

इसलिए, टालना using namespace X;भविष्य के प्रूफिंग का एक रूप है, यह सुनिश्चित करने का एक तरीका है कि पुस्तकालयों और / या हेडर फ़ाइलों के उपयोग में परिवर्तन एक कार्यक्रम को तोड़ने वाला नहीं है।


14
इस। बूस्ट और एसटीडी में बहुत अधिक ओवरलैप होता है - खासकर सी ++ 11 के बाद से।
einpoklum

1
मैंने एक बार ऐसा किया और कठिन तरीके से सबक सीखा। अब मैं कभी भी usingफंक्शन डेफिनिशन के बाहर का उपयोग नहीं करता हूं और शायद ही कभी उपयोग करता हूं using namespace
फेर्रुकियो

210

लघु संस्करण: usingहेडर फ़ाइलों में वैश्विक घोषणाओं या निर्देशों का उपयोग न करें । कार्यान्वयन फ़ाइलों में उनका उपयोग करने के लिए स्वतंत्र महसूस करें। यहाँ क्या हर्ब सटर और आंद्रेई अलेक्जेंड्रेस्कु के सी ++ कोडिंग मानकों में इस मुद्दे के बारे में कहना है (जोर देना मेरे लिए है):

सारांश

Namespace usings आपकी सुविधा के लिए हैं, न कि आपके लिए दूसरों पर जुल्म ढाने के लिए: कभी भी # घोषणापत्र के निर्देश से पहले एक प्रयोग घोषणा या एक प्रयोग निर्देश नहीं लिखें।

कोरोलरी: हेडर फ़ाइलों में, निर्देशों का उपयोग करके या घोषणाओं का उपयोग करके नाम-स्तर नहीं लिखें; इसके बजाय, स्पष्ट रूप से नामस्थान-सभी नामों को अर्हता प्राप्त करते हैं। (दूसरा नियम पहले से अनुसरण करता है, क्योंकि हेडर कभी नहीं जान सकते हैं कि उनके बाद अन्य हेडर #includes क्या प्रदर्शित कर सकते हैं।)

विचार-विमर्श

संक्षेप में: आपको #include निर्देशों के बाद अपने कार्यान्वयन फाइलों में उदारतापूर्वक घोषणाओं और निर्देशों का उपयोग करके नाम स्थान का उपयोग करना चाहिए और इसके बारे में अच्छा महसूस करना चाहिए। इसके विपरीत बार-बार जोर देने के बावजूद, घोषणाओं और निर्देशों का उपयोग करने वाले नाम स्थान बुराई नहीं हैं और वे नाम स्थान के उद्देश्य को नहीं हराते हैं। बल्कि, वे हैं जो नामस्थानों को प्रयोग करने योग्य बनाते हैं


4
यहां केवल एक और प्रोग्रामर की राय है, लेकिन जब मैं इस कथन से 100% सहमत हूं कि शब्द usingको हेडर में कभी भी प्रकट नहीं होना चाहिए, तो मुझे using namespace xyz;आपके लाइसेंस के लिए मुफ्त लाइसेंस के बारे में आश्वस्त नहीं होना चाहिए , खासकर अगर xyzयह है std। मैं using std::vector;फॉर्म का उपयोग करता हूं , क्योंकि यह केवल नाम स्थान से छद्म वैश्विक दायरे में एक तत्व को खींचता है, इसलिए टक्कर का बहुत कम जोखिम होता है।
dgnuff

2
ऑर्बिट में @Lightness दौड़ आप निश्चित रूप से अपनी राय के हकदार हैं। यदि आप इस उत्तर में दी गई सलाह से सहमत नहीं हैं, तो स्पष्टीकरण में कुछ प्रयास किया गया था, तो अधिक उपयोगी होगा। विशेष रूप से यह समझना दिलचस्प होगा कि नामस्थानों का क्या मतलब है अगर उन्हें 'उपयोग' करना बुरा है? क्यों न केवल चीजों को नाम दें std_cout के बजाय std :: cout ... C ++ / namespace के रचनाकारों को कुछ विचार रहा होगा जब उन्होंने उन्हें बनाने की जहमत उठाई थी।
nyholku

1
@nyholku: कोई ज़रूरत नहीं - अधिकांश अन्य उत्तर वही कारण देते हैं जो मैं करूंगा। इसके अलावा ":)" नोट करने में कोई संकोच न करें, मैंने अपनी टिप्पणी में संलग्न किया! और मैंने यह नहीं कहा कि नाम स्थान खराब हैं।
को ऑर्बिट

हाँ, मैंने देखा कि :) लेकिन IMO जवाब के अधिकांश (जो इस ऋषि सलाह के खिलाफ जाते हैं) गुमराह हैं (ऐसा नहीं है कि मैंने कोई भी आँकड़े बनाए हैं कि अब बहुमत क्या है)। यदि आप सहमत हैं कि नाम स्थान 'बुरा नहीं है' तो आप कह सकते हैं कि आपको लगता है कि वे इस उत्तर से असहमत हैं तो वे कहां तक ​​उचित हैं?
निहलोकू

मैं मदद नहीं कर सकता, लेकिन लगता है कि using namespaceबुराई की तरह gotoबुराई है। दोनों के वैध उपयोग हैं, लेकिन 1000 में से 999 बार वे गलत उपयोग किए जाएंगे। तो, हाँ, using namespaceस्रोत के साथ आप अन्य के नाम स्थान को प्रदूषित नहीं करेंगे, साफ-सुथरा। लेकिन यह अभी भी आपको कॉल करने वाले + से उत्पन्न होने वाले "मज़े" के खिलाफ आपकी रक्षा नहीं करेगा (अंतर्निहित फू: :) और अचानक कोड ब्रेकिंग (संबंधित परिवर्तनों के बिना) सिर्फ इसलिए क्योंकि कहीं और जोड़ा गया, जो सिर्फ एक बेहतर होता है मैच (और इस तरह अब इसके बजाय कहा जाता है)using namespace Foousing namespace Barbaz(xyz)Bar::baz()
चारोनएक्स

122

किसी को usingवैश्विक दायरे में निर्देश का उपयोग नहीं करना चाहिए , विशेष रूप से हेडर में। हालाँकि, ऐसी स्थितियाँ हैं जहाँ यह हेडर फ़ाइल में भी उचित है:

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; // No problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

यह स्पष्ट योग्यता ( std::sin, std::cos...) से बेहतर है , क्योंकि यह छोटा है और उपयोगकर्ता परिभाषित फ्लोटिंग पॉइंट प्रकार ( तर्क-निर्भर लुकअप (ADL) के माध्यम से ) के साथ काम करने की क्षमता रखता है ।


9
मुझे खेद है, लेकिन मैं इससे बहुत असहमत हूं।
बिली ओनेल

4
@ बिली: यूजरलीब :: कॉस (यूजरलिब :: सुपरिंट) को कॉल करने का समर्थन करने का कोई अन्य तरीका नहीं है। हर सुविधा का एक उपयोग है।
ज़ेन लिंक्स

17
@Zan: बेशक वहाँ है। using std::cos;, using std::sinआदि मुद्दा हालांकि यह है कि किसी भी अच्छी तरह से डिजाइन किया userlibजा रहा है उनके अंदर sinऔर cosअपने स्वयं के नामस्थान के रूप में अच्छी तरह से है, तो यह वास्तव में आपकी मदद नहीं करता है। (जब तक using namespace userlibइस टेम्पलेट से पहले using namespace stdकोई ऐसा नहीं है और यह उतना ही बुरा है - और इसका दायरा सीमित नहीं है।) इसके अलावा, इस तरह का एकमात्र कार्य जो मुझे कभी भी होता है swap, और ऐसे मामलों में मैं सिर्फ एक टेम्पलेट बनाने की सलाह दूंगा। की विशेषज्ञता std::swapऔर पूरी समस्या से बचने।
बिली ओनली

11
@ बिलियन: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)(कोई फ़ंक्शन टेम्पलेट आंशिक विशेषज्ञता (FTPS) नहीं है, इसलिए कभी-कभी आपको इसके बजाय ओवरलोडिंग का सहारा लेना पड़ता है ।
sbi

38
@ बिलियन: आपकी (7-बार-अप!) टिप्पणी गलत है - आपके द्वारा वर्णित स्थिति ठीक वैसी ही है जैसे एडीएल को कवर करने के लिए डिज़ाइन की गई थी। संक्षेप में, अगर xहै एक या अधिक "जुड़े नामस्थान" (उदाहरण के लिए अगर यह में परिभाषित किया गया था namespace userlib) तो किसी भी समारोह कॉल है कि लगता है कि cos(x)होगा अतिरिक्त उन नामस्थान में देखो - बिना किसी भी using namespace userlib;पहले से आवश्यक किया जा रहा है। ज़ैन लिंक्स सही है (और C ++ नाम
लुकिंग बाइज़ेंटाइन है

97

विश्व स्तर पर इसका उपयोग न करें

इसे "खराब" माना जाता है जब इसे विश्व स्तर पर उपयोग किया जाता है । चूंकि:

  • आपके द्वारा नामांकित किए जा रहे नामस्थान को आप अव्यवस्थित कर देते हैं।
  • पाठकों को यह देखने में कठिनाई होगी कि कोई विशेष पहचानकर्ता कहां से आता है, जब आप कई का उपयोग करते हैं using namespace xyz
  • जो भी हो दूसरे के लिए सच हैआपके स्रोत कोड के पाठकों के कुछ भी सच है, उसमें से सबसे अधिक बार पढ़ने वाले के लिए और भी अधिक सच है: स्वयं। एक-दो साल में वापस आकर देख लेंगे ...
  • यदि आप केवल आपके बारे में बात करते हैं, using namespace stdतो आपके द्वारा हड़पे गए सभी सामानों के बारे में पता नहीं चल सकता है - और जब आप एक और जोड़ते हैं #includeया एक नया सी ++ संशोधन करते हैं, तो आपको नाम संघर्ष मिल सकता है जिसके बारे में आपको जानकारी नहीं थी।

आप इसे स्थानीय स्तर पर उपयोग कर सकते हैं

आगे बढ़ो और इसे स्थानीय रूप से (लगभग) स्वतंत्र रूप से उपयोग करें। यह, निश्चित रूप से, आपको पुनरावृत्ति से बचाता हैstd:: - और दोहराव भी बुरा है।

स्थानीय रूप से इसका उपयोग करने के लिए एक मुहावरा

C ++ 03 में एक मुहावरा था - बॉयलरप्लेट कोड - swapअपनी कक्षाओं के लिए एक फ़ंक्शन लागू करने के लिए। यह सुझाव दिया गया था कि आप वास्तव में एक स्थानीय का उपयोग करें using namespace std- या कम से कम using std::swap:

class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

यह निम्नलिखित जादू करता है:

  • संकलक के std::swapलिए value_, यानी का चयन करेंगेvoid std::swap(int, int)
  • यदि आपके पास एक अधिभार है void swap(Child&, Child&) लागू है तो संकलक इसे चुन लेगा।
  • यदि आपके पास ऐसा अधिभार नहीं है, तो संकलक उपयोग करेगा void std::swap(Child&,Child&)और इन सबसे अच्छी अदला-बदली का प्रयास करेगा ।

C ++ 11 के साथ इस पैटर्न का उपयोग करने का कोई कारण नहीं है। std::swapसंभावित अधिभार को खोजने और इसे चुनने के लिए कार्यान्वयन को बदल दिया गया था।


5
"संभावित ओवरलोड को खोजने और उसे चुनने के लिए एसटीडी :: स्वैप का कार्यान्वयन बदल दिया गया था।" - क्या? क्या अापको उस बारे में पूर्ण विशवास है? हालांकि यह सच है कि swapपहली जगह में कस्टम प्रदान करना C ++ 11 में इतना महत्वपूर्ण नहीं है, क्योंकि std::swapयह अधिक लचीला है (चाल शब्दार्थों का उपयोग करता है)। लेकिन std::swapस्वचालित रूप से अपने स्वयं के कस्टम स्वैप को चुनना, यह मेरे लिए बिल्कुल नया है (और मुझे वास्तव में इस पर विश्वास नहीं है)।
ईसाई रौ

@ChristianRau मुझे ऐसा लगता है, हाँ। मैंने इसे SO पर कहीं पढ़ा। हम हमेशा हावर्ड से पूछ सकते हैं , उसे पता होना चाहिए। मैं अब खुदाई और खुदाई कर रहा हूं ...
टोबी

14
स्वैप मामले में भी, स्पष्ट (और शुक्र से अधिक सामान्य) मुहावरे के using std::swap;बजाय लिखना है using namespace std;। अधिक विशिष्ट मुहावरे के कम दुष्प्रभाव होते हैं और इसलिए यह कोड को अधिक बनाए रखता है।
एड्रियन मैक्कार्थी

11
अंतिम वाक्य गलत है। C ++ में 11 कक्षा स्वैप दो चरण आधिकारिक तौर पर के रूप में धन्य किया गया था सही कॉल करने के लिए जिस तरह से swap, और मानक में विभिन्न अन्य स्थानों पर वे कहते हैं कहने के लिए बदल रहे थे swapकि जैसे (नायब जैसा कि ऊपर कहा गया है, using std::swapसही तरीके से, नहीं है using namespace std)। लेकिन std::swapखुद को सशक्त रूप से परिवर्तित नहीं किया गया था कि वे कुछ अन्य को ढूंढ swapसकें और इसका उपयोग कर सकें। तो std::swapकहा जाता हो जाता है, तो std::swapइस्तेमाल किया जाता है।
जोनाथन वकेली

3
यह using std::swapस्थानीय नाम स्थान को कम करने के लिए स्थानीय रूप से टाइप करने के लिए समझदार हो सकता है , जबकि एक ही समय में स्व-दस्तावेजीकरण कोड बना सकता है। आप शायद ही कभी पूरे एसटीडी नामस्थान में रुचि रखते हैं, इसलिए बस उन हिस्सों को बाहर
निकालिए

79

आप सही हेडर फाइल आयात करते हैं तो आप अचानक नामों की तरह है hex, left, plusया countअपने वैश्विक विस्तार में। यह आश्चर्य की बात हो सकती है यदि आप जागरूक नहीं हैं std::जिसमें ये नाम शामिल हैं। यदि आप स्थानीय रूप से इन नामों का उपयोग करने का प्रयास करते हैं, तो यह कुछ भ्रम पैदा कर सकता है।

यदि सभी मानक सामान अपने नामस्थान में हैं, तो आपको अपने कोड या अन्य पुस्तकालयों के साथ नाम टकराव के बारे में चिंता करने की आवश्यकता नहीं है।


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

हालांकि, यदि आप शामिल नहीं हैं, तो उचित नहीं है <iomanip>। फिर भी, अच्छी बात है।
einpoklum

48

एक और कारण हैरान करने वाला है।

अगर मैं देखूं cout << blahतो इसके बजाय std::cout << blahमुझे लगता है: यह क्या है cout? क्या यह सामान्य है cout? क्या यह कुछ खास है?


25
क्या यह एक मजाक है? मैं वास्तव में नहीं बता सकता। यदि नहीं, तो मैं व्यक्तिगत रूप से यह मान लूंगा कि यह 'कॉट' है, जब तक कि आप कोड पर भरोसा नहीं करते हैं अन्यथा यह एक BEJOND MAJOR कोड गंध, IMO होगा। ... और अगर आपको कोड पर भरोसा नहीं है तो आप इसे पहली जगह क्यों इस्तेमाल कर रहे हैं? ध्यान दें कि मैं "विश्वास नहीं कर रहा हूँ !!" यदि आप कहते हैं, तो यह थोड़ी दूर की बात लगती है, जैसे कि GitHub या किसी और चीज़ से किसी परिचित लाइब्रेरी से निपटना।
ब्रेंट रिटेनहाउस

28
@BrentRittenhouse coutएक बुरा उदाहरण है क्योंकि हर कोई इसे पहचानता है। लेकिन futureएक वित्तीय ऐप में कल्पना कीजिए । क्या किसी निर्दिष्ट तिथि पर कुछ खरीदना या बेचना अनुबंध है? नहीं, यह नहीं है। यदि कोड ने कहा कि std::futureआप इतनी आसानी से भ्रमित नहीं होंगे।
जेम्स हॉलिस

2
@BrentRittenhouse शायद थोड़ा खराब उदाहरण है, कम से कम चार अलग-अलग पुस्तकालय हैं जिनमें कॉट हैं। हो सकता है "यह मानक पुस्तकालय है? Libstdc ++? Stl? कुछ और?" और नहीं, हर कोई नहीं जानता कि std :: cout, कम से कम स्वाभाविक रूप से, 6 में से 6 नए श्रमिक जो हमें नहीं मिलते हैं। क्योंकि शिक्षा का पाठ्यक्रम शिक्षा में उन लोगों का उपयोग नहीं करता है। मुझे प्रिंटआउट का पीछा करना होगा। या डिबग () - क्यूटी से।
स्विफ्ट - शुक्रवार पाई

1
वास्तव में? यह C ++ पर कई पुस्तकों के sooo के पहले अध्याय के पहले उदाहरण में बहुत सुंदर है, अगर कुछ भी (सम्मिलन ऑपरेटर उपयोग के साथ) केवल C ++ है जो कुछ नए शरीर जानते हैं।
मैकेंज़्म

@mckenzm मैं इसे अव्यवस्था को कम करने के लिए एक पुस्तक या व्याख्यान नोट्स में रख सकता हूं, लेकिन कोड में नहीं
मार्टिन बेकेट

45

अनुभवी प्रोग्रामर अपनी समस्याओं को हल करते हैं और जो भी नई समस्याएं पैदा करते हैं उनसे बचने का उपयोग करते हैं, और वे इस सटीक कारण के लिए हेडर-फाइल-स्तर-निर्देशन से बचते हैं।

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

ये अच्छे कारण क्या हैं ? कभी-कभी प्रोग्रामर स्पष्ट रूप से एडीएल को बंद करना चाहते हैं, दूसरी बार वे अव्यवस्था करना चाहते हैं।

तो निम्नलिखित ठीक हैं:

  1. फ़ंक्शन-स्तर का उपयोग-निर्देश और फ़ंक्शन के कार्यान्वयन के अंदर का उपयोग-घोषणाएं
  2. स्रोत-फ़ाइल-स्तर स्रोत फ़ाइलों के अंदर-घोषणाओं का उपयोग करना
  3. (कभी-कभी) स्रोत-फ़ाइल-स्तर का उपयोग-निर्देश

43

मैं सहमत हूं कि इसका विश्व स्तर पर उपयोग नहीं किया जाना चाहिए, लेकिन यह स्थानीय रूप से उपयोग करने के लिए इतना बुरा नहीं है, जैसे कि ए namespace। यहाँ "C ++ प्रोग्रामिंग लैंग्वेज" से एक उदाहरण दिया गया है :

namespace My_lib {

    using namespace His_lib; // Everything from His_lib
    using namespace Her_lib; // Everything from Her_lib

    using His_lib::String; // Resolve potential clash in favor of His_lib
    using Her_lib::Vector; // Resolve potential clash in favor of Her_lib

}

इस उदाहरण में, हमने उनकी रचना से उत्पन्न संभावित नाम की झड़पों और अस्पष्टताओं को हल किया।

नाम स्पष्ट रूप से वहां घोषित किए गए हैं (जैसे-घोषणा-घोषणाओं द्वारा घोषित नामों सहित His_lib::String) एक प्रयोग-निर्देश ( using namespace Her_lib) द्वारा एक और दायरे में सुलभ किए गए नामों पर प्राथमिकता लेते हैं ।


29

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

हालाँकि, अगर मैं अक्सर 'cout' और 'cin' का उपयोग करता हूँ, तो मैं लिखता हूँ: using std::cout; using std::cin;.cpp फ़ाइल (हेडर फ़ाइल में कभी नहीं जैसा कि यह प्रचार करता है #include)। मुझे लगता है कि कोई भी समझदार कभी एक धारा का नाम होगा coutया cin। ;)


7
यह घोषणा का उपयोग करते हुए एक स्थानीय है , एक प्रयोग निर्देश से बहुत अलग बात है ।
sbi

25

कोड देखना और जानना अच्छा है कि यह क्या करता है। अगर मैं देखूं तो std::coutमुझे पता है कि coutयह stdपुस्तकालय की धारा है । अगर मैं देखता हूं coutतो मुझे नहीं पता। यह पुस्तकालय की धारा हो सकती है । या एक ही फ़ंक्शन में दस लाइनें अधिक हो सकती हैं । या उस फ़ाइल में नामित एक चर । यह कुछ भी हो सकता है।coutstdint cout = 0;staticcout

अब एक लाख लाइन कोड आधार लें, जो विशेष रूप से बड़ा नहीं है, और आप एक बग की खोज कर रहे हैं, जिसका अर्थ है कि आप जानते हैं कि इस दस लाख लाइनों में एक लाइन है जो ऐसा नहीं करती है जो इसे करना चाहिए। cout << 1;एक static intनाम पढ़ सकते हैं cout, इसे एक बिट से बाईं ओर शिफ्ट कर सकते हैं , और परिणाम को फेंक सकते हैं। बग की तलाश में, मुझे यह देखना होगा। क्या आप देख सकते हैं कि मैं वास्तव में कैसे देखना पसंद करता हूं std::cout?

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


4
आप कैसे जानते हैं कि "std :: cout << 1" std namespace में cout नाम का एक स्थिर int नहीं पढ़ रहा है और इसे एक परिणाम से दूर फेंक रहा है? इसके अलावा आप कैसे जानते हैं कि "<<" क्या करता है?) ??? ... ऐसा लगता है कि यह उत्तर 'उपयोग' से बचने के लिए अच्छा डेटा बिंदु नहीं है।
निहलोकू

4
अगर किसी ने std :: cout को पूर्णांक के रूप में पुनर्परिभाषित किया है, तो आपकी समस्या तकनीकी नहीं है, लेकिन सामाजिक - कोई आपके लिए है। (और आपको शायद सभी हेडर को #define true false, etc जैसे चीजों के लिए जांचना चाहिए)
जेरेमी फ्रेज़र

2
जब मैं cout देखता हूं तो मुझे पता है कि यह std :: cout, हमेशा है। अगर मैं गलत हूं, तो यह उस व्यक्ति की समस्या है जिसने इस कोड को लिखा था, मुझे नहीं :)
टीएन डू

22

यह सब जटिलता के प्रबंधन के बारे में है। नेमस्पेस का उपयोग उन चीजों को खींचेगा जिनमें आप नहीं चाहते हैं, और इस तरह संभवतः इसे डीबग करना कठिन हो जाता है (मैं संभवतः कहता हूं)। Std का उपयोग करना :: सभी जगह (अधिक पाठ और वह सब पढ़ना) कठिन है।

पाठ्यक्रमों के लिए घोड़े - अपनी जटिलता का प्रबंधन करें कि आप सबसे अच्छा कैसे कर सकते हैं और सक्षम महसूस करते हैं।


18

विचार करें

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // Uh oh
};

ध्यान दें कि यह एक सरल उदाहरण है। यदि आपके पास 20 और अन्य आयात की फाइलें हैं, तो समस्या का पता लगाने के लिए आपके पास एक टन निर्भरता होगी। इसके बारे में बुरी बात यह है कि आप संघर्षों की परिभाषाओं के आधार पर अन्य मॉड्यूल में असंबंधित त्रुटियां प्राप्त कर सकते हैं।

यह भयानक नहीं है, लेकिन आप इसे हेडर फ़ाइलों या वैश्विक नामस्थान में उपयोग न करके खुद को सिरदर्द से बचाएंगे। यह बहुत ही सीमित दायरे में करने के लिए शायद सब ठीक है, लेकिन मुझे यह स्पष्ट करने में कोई समस्या नहीं है कि अतिरिक्त पाँच वर्णों को स्पष्ट करने के लिए कि मेरे कार्य कहाँ से आ रहे हैं।


18
  1. आपको उन लोगों द्वारा लिखे गए कोड को पढ़ने में सक्षम होना चाहिए, जिनके पास आपकी तुलना में अलग-अलग शैली और सर्वोत्तम प्रथाओं की राय है।

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


17

एक ही समय में कई नामस्थानों का उपयोग करना जाहिर तौर पर आपदा के लिए एक नुस्खा है, लेकिन सिर्फ नामस्थान stdऔर केवल नामस्थान stdका उपयोग करना मेरी राय में एक बड़ी बात नहीं है क्योंकि पुनर्वित्त केवल आपके स्वयं के कोड द्वारा हो सकता है ...

तो बस उन्हें "इंट" या "क्लास" जैसे आरक्षित नामों के रूप में कार्य करने पर विचार करें और यही वह है।

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


टकराव पैदा करना कठिन नहीं है - जैसे छोटे तार min, endऔर नाम स्थान lessमें दिखाई देते हैं std::। लेकिन अधिक, अब std::इसमें हजारों प्रतीक हैं, यह पाठक के लिए यह जानना उपयोगी है कि एक नया प्रतीक जहां वे नहीं जानते हैं वह कहां से आता है।
टॉम स्विरी

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

14

मैं यहां अन्य लोगों से सहमत हूं, लेकिन मैं पठनीयता के बारे में चिंताओं को दूर करना चाहूंगा - आप अपनी फ़ाइल, फ़ंक्शन या क्लास घोषणा के शीर्ष पर केवल टाइपराइफ का उपयोग करके उस सब से बच सकते हैं।

मैं आमतौर पर अपनी कक्षा की घोषणा में इसका उपयोग करता हूं क्योंकि एक कक्षा में विधियां समान डेटा प्रकारों (सदस्यों) से निपटने के लिए होती हैं और एक टाइपडेफ एक ऐसा नाम असाइन करने का अवसर है जो वर्ग के संदर्भ में सार्थक है। यह वास्तव में वर्ग विधियों की परिभाषाओं में पठनीयता को सहायक बनाता है।

// Header
class File
{
   typedef std::vector<std::string> Lines;
   Lines ReadLines();
}

और कार्यान्वयन में:

// .cpp
Lines File::ReadLines()
{
    Lines lines;
    // Get them...
    return lines;
}

विरोध के रूप में:

// .cpp
vector<string> File::ReadLines()
{
    vector<string> lines;
    // Get them...
    return lines;
}

या:

// .cpp
std::vector<std::string> File::ReadLines()
{
    std::vector<std::string> lines;
    // Get them...
    return lines;
}

बस एक छोटी सी टिप्पणी, जबकि typedef उपयोगी है मैं एक ऐसा वर्ग बनाने पर विचार करूँगा जो typedef का उपयोग करने के बजाय लाइन्स का प्रतिनिधित्व करता है।
ईयाल सोलनिक

14

चिंता को स्पष्ट करने के लिए एक ठोस उदाहरण। कल्पना कीजिए कि आपके पास एक ऐसी स्थिति है जहां आपके पास दो पुस्तकालय हैं, fooऔर barप्रत्येक अपने स्वयं के नामस्थान के साथ:

namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

अब कहते हैं कि आप अपने स्वयं के कार्यक्रम में उपयोग fooऔर barएक साथ इस प्रकार हैं:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

इस बिंदु पर सब कुछ ठीक है। जब आप अपना प्रोग्राम चलाते हैं तो यह 'कुछ करता है'। लेकिन बाद में आप अपडेट करें barऔर मान लें कि यह बदल गया है:

namespace bar {
    void a(float) { /* Does something completely different */ }
}

इस बिंदु पर आपको एक कंपाइलर त्रुटि मिलेगी:

using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

तो आपको यह स्पष्ट करने के लिए कुछ रखरखाव करने की आवश्यकता होगी कि 'ए' का मतलब है foo::a। यह अवांछनीय है, लेकिन सौभाग्य से यह बहुत आसान है (बस foo::सभी कॉल के सामने जोड़ेंa कि संकलक अस्पष्ट के रूप में चिह्नित करता है)।

लेकिन एक ऐसे वैकल्पिक परिदृश्य की कल्पना करें जहां बार बदले जाने के बजाय बार बदले:

namespace bar {
    void a(int) { /* Does something completely different */ }
}

इस बिंदु पर आपका कॉल a(42)अचानक और 'कुछ' करने के बजाय 'कुछ बिल्कुल अलग' करने के bar::aबजाय बांधता है foo::a। कोई संकलक चेतावनी या कुछ भी नहीं। आपका कार्यक्रम चुपचाप पहले की तुलना में कुछ अलग करना शुरू कर देता है।

जब आप किसी ऐसे नामस्थान का उपयोग करते हैं, तो आप इस तरह से एक परिदृश्य का उपयोग कर रहे होते हैं, जिसके कारण लोग नामस्थानों का उपयोग करने में असहज होते हैं। किसी नाम स्थान में जितनी अधिक चीजें होती हैं, संघर्ष का खतरा उतना ही अधिक होता है, इसलिए लोग नाम स्थान का उपयोग करके और भी असहज हो सकते हैंstd अन्य नेमस्पेस की तुलना में (उस नेमस्पेस में चीजों की संख्या के कारण) ।

अंततः यह रिटेलिबिलिटी बनाम विश्वसनीयता / स्थिरता के बीच का व्यापार है। पठनीयता भी इसमें कारक हो सकती है, लेकिन मैं उस रास्ते के लिए तर्क देख सकता था। आम तौर पर मैं कहूंगा कि विश्वसनीयता और रख-रखाव अधिक महत्वपूर्ण हैं, लेकिन इस मामले में आप काफी दुर्लभ विश्वसनीयता / रख-रखाव प्रभाव के लिए निरंतरता लागत का भुगतान करेंगे। 'सर्वश्रेष्ठ' व्यापार बंद आपकी परियोजना और आपकी प्राथमिकताओं पर निर्धारित करेगा।


दूसरा परिदृश्य मेरे लिए सौदा तय करता है। फिर से कोई नामस्थान नहीं। हुड के नीचे चल रही कार्यक्षमता में ऐसे सूक्ष्म परिवर्तन नहीं हो सकते हैं।
safe_malloc

13

एक नाम स्थान एक नामित क्षेत्र है। नामों का उपयोग समूह से संबंधित घोषणाओं के लिए और अलग-अलग वस्तुओं को अलग-अलग रखने के लिए किया जाता है। उदाहरण के लिए, दो अलग-अलग विकसित पुस्तकालय अलग-अलग वस्तुओं को संदर्भित करने के लिए एक ही नाम का उपयोग कर सकते हैं, लेकिन एक उपयोगकर्ता अभी भी दोनों का उपयोग कर सकता है:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    // ...
}

namespace Yourlib{
    class Stack{ /* ... */ };
    // ...
}

void f(int max) {
    Mylib::Stack<int> s1(max); // Use my stack
    Yourlib::Stack    s2(max); // Use your stack
    // ...
}

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

void f(int max) {
    using namespace Mylib; // Make names from Mylib accessible
    Stack<int> s1(max); // Use my stack
    Yourlib::Stack s2(max); // Use your stack
    // ...
}

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

स्रोत: बज़्ने स्ट्रॉस्ट्रुप द्वारा सी ++ प्रोग्रामिंग लैंग्वेज का अवलोकन


4
बहुत दिलचस्प है कि यह एक उत्तर जो कि अन्य के मार्गदर्शन पर आधारित है, जिसे
बज़्ने स्ट्रॉस्ट्रुप

@nyholku: देखें इस
sbi

10

एक उदाहरण जहां using namespace stdगिनती की अस्पष्टता के कारण संकलन त्रुटि होती है, जो एल्गोरिथ्म लाइब्रेरी में एक फ़ंक्शन भी है।

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}

2
::count--समस्या सुलझ गयी। आमतौर पर आपके पास std नाम स्थान से कहीं अधिक सामान होगा, उपयोग नाम स्थान निर्देश रखने से आप टाइपिंग से बचा सकते हैं।
PSkocik

यहाँ वास्तविक समस्या यह है कि C ++ में अभी भी नाम स्थान-कम ग्लोबल्स हैं। यह, और यह तथ्य कि 'यह' विधियों में निहित है, इतने सारे कीड़े और समस्याएं पैदा करता है कि मैं उन्हें गिन भी नहीं सकता, यहां तक ​​कि सही 'गिनती' चर के साथ भी। ;)
ऐकेन ड्रम

9

यह आपके सॉफ़्टवेयर या प्रोजेक्ट प्रदर्शन को बदतर नहीं बनाता है। आपके स्रोत कोड की शुरुआत में नामस्थान का समावेश बुरा नहीं है। using namespace stdनिर्देश का समावेश आपकी आवश्यकताओं और जिस तरह से आप सॉफ्टवेयर या प्रोजेक्ट विकसित कर रहे हैं, उसके अनुसार बदलता रहता है।

namespace stdसी ++ मानक कार्य करता है और चर होते हैं। यह नाम स्थान तब उपयोगी होता है जब आप अक्सर C ++ मानक फ़ंक्शन का उपयोग करेंगे।

जैसा कि इस पृष्ठ में बताया गया है :

नेमस्पेस std का उपयोग करने वाले कथन को आमतौर पर बुरा व्यवहार माना जाता है। इस कथन का विकल्प उन नामों को निर्दिष्ट करना है, जिनसे पहचानकर्ता गुंजाइश ऑपरेटर का उपयोग करता है (: :) हर बार जब हम एक प्रकार की घोषणा करते हैं।

और इस राय को देखें :

जब आप नेमस्पेस का भारी उपयोग करते हैं तो अपनी सोर्स फाइल में "नेमस्पेस std का उपयोग" करने में कोई समस्या नहीं है और यह सुनिश्चित करें कि कुछ भी नहीं टकराएगा।

कुछ लोगों ने कहा था कि using namespace stdआपके स्रोत फ़ाइलों में शामिल करने के लिए एक बुरा अभ्यास है क्योंकि आप उस नामस्थान से सभी कार्यों और चर को आमंत्रित कर रहे हैं। जब आप एक नए फ़ंक्शन को उसी नाम से परिभाषित करना चाहेंगे, जैसे कि namespace stdआप में निहित एक अन्य फ़ंक्शन फ़ंक्शन को अधिभारित करेगा और यह संकलन या निष्पादित करने के कारण समस्याएं पैदा कर सकता है। जैसा कि आप उम्मीद करते हैं, यह संकलन या निष्पादित नहीं करेगा।

जैसा कि इस पृष्ठ में बताया गया है :

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

...

अब विकास के एक बाद के चरण में, हम कॉट के एक और संस्करण का उपयोग करना चाहते हैं, जिसे कस्टम में कुछ लाइब्रेरी में "फू" (उदाहरण के लिए) कहा जाता है।

...

ध्यान दें कि कैसे एक अस्पष्टता है, किस पुस्तकालय से संकेत मिलता है? कंपाइलर इसका पता लगा सकता है और कार्यक्रम को संकलित नहीं कर सकता है। सबसे खराब स्थिति में, प्रोग्राम अभी भी संकलित कर सकता है लेकिन गलत फ़ंक्शन को कॉल कर सकता है, क्योंकि हम कभी भी निर्दिष्ट नहीं करते हैं कि पहचानकर्ता किस नामस्थान का है।


8

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


7

"नामस्थान std का उपयोग क्यों किया जाता है?" C ++ में एक बुरा अभ्यास माना जाता है? "

मैंने इसे दूसरे तरीके से रखा: क्यों कुछ लोगों द्वारा बोझिल माने जाने वाले पांच अतिरिक्त पात्रों को टाइप किया जा रहा है?

उदाहरण के लिए संख्यात्मक सॉफ्टवेयर का एक टुकड़ा लिखने पर विचार करें। जब मैं "वेक्टर" समस्या डोमेन के सबसे महत्वपूर्ण अवधारणाओं में से एक है, तो मैं सामान्य "std :: वेक्टर" को काटकर अपने वैश्विक नामस्थान को प्रदूषित करने पर भी विचार क्यों करूंगा?


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

5
हर बार इसके 5 अतिरिक्त चार्ट नहीं, यह 5 चार्ट है और शायद एक जोड़ी माउस एक मेनू को खींचने के लिए क्लिक करता है और अपनी पसंद के संपादक में एक खोजें और बदलें।
डेवलेली

1
पठनीयता। cout << hex << setw(4) << i << endl;पढ़ने में आसान हैstd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz

16
और इससे भी बदतर: std::map<std::string,std::pair<std::string,std::string>>की तुलना में भयानक है map<string,pair<string,string>>
oz1cz

4
यह एक अच्छा अभ्यास है अपने STL कंटेनरों को टाइप करने के लिए वैसे भी std :: वहाँ वास्तव में कोई फर्क नहीं पड़ता। और C ++ 11 ने हमें ऑटो कीवर्ड लाया है जो पुनरावृत्तियों का उपयोग करते समय चीजों को और भी आसान बनाता है।
९'१६

7

मैं अन्य लोगों से सहमत हूँ - यह नाम संघर्ष, अस्पष्टता के लिए पूछ रहा है और फिर तथ्य यह है कि यह कम स्पष्ट है। जबकि मैं इसका उपयोग देख सकता हूं using, मेरी व्यक्तिगत प्राथमिकता इसे सीमित करना है। मैं यह भी दृढ़ता से विचार करूंगा कि कुछ अन्य लोगों ने क्या कहा:

यदि आप एक फ़ंक्शन नाम ढूंढना चाहते हैं, जो काफी सामान्य नाम हो सकता है, लेकिन आप इसे केवल stdनामस्थान (या रिवर्स - आप उन सभी कॉल को बदलना चाहते हैं , जो नाम स्थान std, नाम स्थान X, ...) में नहीं चाहते हैं तो फिर आप ऐसा करने का प्रस्ताव कैसे देते हैं?

आप इसे करने के लिए एक कार्यक्रम लिख सकते हैं, लेकिन क्या अपनी परियोजना को बनाए रखने के लिए कार्यक्रम लिखने के बजाय अपने प्रोजेक्ट पर काम करने में समय बिताना बेहतर नहीं होगा?

व्यक्तिगत रूप से, मैं वास्तव में std::उपसर्ग को बुरा नहीं मानता। मुझे यह नहीं की तुलना में अधिक पसंद है। मुझे नहीं पता कि क्या है क्योंकि यह स्पष्ट है और मुझसे कहता है "यह मेरा कोड नहीं है ... मैं मानक पुस्तकालय का उपयोग कर रहा हूं" या अगर यह कुछ और है, लेकिन मुझे लगता है कि यह अच्छा लग रहा है। यह अजीब हो सकता है कि मुझे हाल ही में C ++ मिला (अभी भी C और अन्य भाषाएं बहुत अधिक समय तक इस्तेमाल की गई हैं और C मेरी सभी समय की पसंदीदा भाषा है, विधानसभा के ठीक ऊपर)।

एक और बात है, हालांकि यह कुछ हद तक ऊपर से संबंधित है और अन्य क्या बताते हैं। हालांकि यह बुरा अभ्यास हो सकता है, मैं कभी-कभी std::nameमानक पुस्तकालय संस्करण और कार्यक्रम-विशिष्ट कार्यान्वयन के लिए नाम के लिए आरक्षित करता हूं । हां, वास्तव में यह आपको काट सकता है और आपको मुश्किल से काट सकता है, लेकिन यह सब नीचे आता है कि मैंने इस परियोजना को खरोंच से शुरू किया था, और मैं इसके लिए एकमात्र प्रोग्रामर हूं। उदाहरण: मैं ओवरलोड करता हूं std::stringऔर इसे कॉल करता हूं string। मेरे पास सहायक जोड़ हैं। मैंने अपने C और Unix (+ Linux) प्रवृत्ति के कारण निचले मामलों के नामों के कारण इसे आंशिक रूप से किया।

इसके अलावा, आपके पास नाम स्थान उपनाम हो सकते हैं। यहां एक उदाहरण है जहां यह उपयोगी है जिसे शायद संदर्भित नहीं किया गया है। मैं C ++ 11 मानक का उपयोग करता हूं और विशेष रूप से libstdc ++ के साथ। खैर, इसका पूरा std::regexसमर्थन नहीं है । ज़रूर, यह संकलित करता है, लेकिन यह प्रोग्रामर के अंत में एक त्रुटि होने की तर्ज पर एक अपवाद फेंकता है। लेकिन यह कार्यान्वयन की कमी है।

तो यहाँ है कि मैंने इसे कैसे हल किया। बूस्ट के रेगेक्स को स्थापित करें, और इसे लिंक करें। फिर, मैं निम्न कार्य करता हूं ताकि जब libstdc ++ ने इसे पूरी तरह से लागू किया हो, तो मुझे केवल इस ब्लॉक को हटाने की आवश्यकता है और कोड समान रहता है:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;
}

मैं इस पर बहस नहीं करूंगा कि यह एक बुरा विचार है या नहीं। मैं हालांकि यह तर्क दूंगा कि यह मेरी परियोजना के लिए इसे साफ रखता है और एक ही समय में इसे विशिष्ट बनाता है: सच है, मुझे बूस्ट का उपयोग करना होगा, लेकिन मैं इसका उपयोग कर रहा हूं जैसे कि libstdc ++ अंततः होगा। हां, अपना स्वयं का प्रोजेक्ट शुरू करना और बहुत शुरुआत में एक मानक (...) के साथ शुरू करना रखरखाव, विकास और परियोजना से जुड़ी हर चीज की मदद करने के साथ बहुत लंबा रास्ता तय करता है!

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

जैसा कि यह है, मैं अभी भी सी के प्रति बहुत पक्षपाती हूं और सी ++ के खिलाफ पक्षपाती हूं। विवरण बख्शते हुए, मैं सी पर जो काम करता हूं उसमें से अधिकांश सी अधिक फिट होता है (लेकिन यह एक अच्छा व्यायाम और खुद को बनाने का एक अच्छा तरीका है। एक और भाषा सीखें और बी। वस्तु / वर्गों / आदि के खिलाफ कम पक्षपाती न होने की कोशिश करें जो शायद बेहतर कहा गया है। कम बंद दिमाग वाले, कम अभिमानी और अधिक स्वीकार करने वाले।)। लेकिन क्या है (, यह नहीं है यह काफी सामान्य है?) मैं वास्तव में सूची का उपयोग करते हैं, और प्रकार (एक ही बात) दो कि एक नाम टकराव का कारण होता है, तो मैं ऐसा करने थे नाम हैं: उपयोगी क्या कुछ पहले से ही सुझाव दिया है using namespace std;, और इसलिए उस अंत तक, मैं विशिष्ट होना पसंद करता हूं, नियंत्रण में और यह जानना कि अगर मैं इसे मानक उपयोग करने का इरादा रखता हूं तो मुझे इसे निर्दिष्ट करना होगा। सीधे शब्दों में कहें: कोई अनुमति नहीं दी।

और के रूप में बूस्ट के regex हिस्सा बनाने के लिए std। मैं भविष्य के एकीकरण के लिए ऐसा करता हूं और फिर से, मैं पूरी तरह से मानता हूं कि यह पूर्वाग्रह है - मुझे नहीं लगता कि यह उतना ही बदसूरत है boost::regex:: ...। वास्तव में, यह मेरे लिए एक और बात है। C ++ में बहुत सी ऐसी चीजें हैं जो मुझे अभी भी लुक्स और तरीकों में पूरी तरह से स्वीकार करने के लिए बाकी हैं (एक अन्य उदाहरण: varadic टेम्प्लेट्स बनाम var आर्ग्युमेंट्स [हालाँकि मैं मानता हूं कि varadic टेम्प्लेट बहुत उपयोगी हैं!])। यहां तक ​​कि जो मैं स्वीकार करता हूं वह मुश्किल था, और मेरे पास अभी भी उनके साथ मुद्दे हैं।


1
stdनामस्थान का विस्तार अपरिभाषित व्यवहार है और इस तरह कभी नहीं किया जाना चाहिए।
ताम्बे

7

मेरे अनुभवों से, यदि आपके पास कहने के लिए कई पुस्तकालय हैं cout, लेकिन एक अलग उद्देश्य के लिए आप गलत का उपयोग कर सकते हैं cout

उदाहरण के लिए, यदि मैं टाइप करता हूं, using namespace std;और using namespace otherlib;केवल टाइप करता हूं cout(जो दोनों में होता है), बजाय std::cout(या 'otherlib::cout'), आप गलत का उपयोग कर सकते हैं, और त्रुटियां प्राप्त कर सकते हैं। यह उपयोग करने के लिए बहुत अधिक प्रभावी और कुशल है std::cout


6

अयोग्य आयातित पहचानकर्ताओं के साथ आपको यह जानने के लिए grep जैसे बाहरी खोज टूल की आवश्यकता होती है जहां पहचानकर्ता घोषित किए जाते हैं। इससे प्रोग्राम की शुद्धता के बारे में तर्क करना कठिन हो जाता है।


6

यह इस पर निर्भर करता है कि यह कहाँ स्थित है। यदि यह एक सामान्य शीर्षक है, तो आप नामस्थान के मान को वैश्विक नामस्थान में मर्ज करके कम कर रहे हैं। ध्यान रखें, यह मॉड्यूल ग्लोबल्स बनाने का एक साफ तरीका हो सकता है।


6

यह एक बुरा अभ्यास है, जिसे अक्सर वैश्विक नामस्थान प्रदूषण के रूप में जाना जाता है। समस्याएँ तब हो सकती हैं जब एक से अधिक नामस्थान पर हस्ताक्षर के साथ एक ही फ़ंक्शन नाम होता है, तो यह संकलक के लिए अस्पष्ट होगा कि वह किसे कॉल करे और जब आप अपने फ़ंक्शन कॉल के साथ नाम स्थान निर्दिष्ट कर रहे हों तो यह सब टाला जा सकता है std::cout। उम्मीद है की यह मदद करेगा। :)


5

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

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

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


यह देखते हुए कि कितने लोग उपयोगी मानक पुस्तकालय कार्यों ( <algorithm>उदाहरण के लिए चीजों को फिर से बनाना ) से अनजान हैं , यह कल्पना करना थोड़ा सा खिंचाव लगता है कि वही लोग मज़बूती से उन पहचानकर्ताओं से बच सकते हैं। अपने स्वयं के कोड के माध्यम से देखें और मुझे बताएं कि आपके पास कभी भी चर या फ़ंक्शन नहीं है count। या distance, या log, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, left, आदि नहीं सभी पहचानकर्ता में उल्लेख करने के लिए अभी तक नहीं stdहै कि अपने कोड टूट जाएगा जब सी ++ 35 बाहर आता है ...
टोबी स्पीट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.