Std Namespace का उपयोग करना


110

एसटीडी नेमस्पेस के संबंध में 'उपयोग' करने के बारे में अलग-अलग विचार हैं।

कुछ कहते हैं कि ' using namespace std' का प्रयोग करें , दूसरे कहते हैं कि उपसर्ग std फ़ंक्शन नहीं हैं, जिनका उपयोग ' std::' के साथ किया जाना है, जबकि अन्य कहते हैं कि कुछ का उपयोग करें:

using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::vector;

उपयोग किए जाने वाले सभी std फ़ंक्शन के लिए।

प्रत्येक का भला - बुरा क्या है?




जवाबों:


131

अधिकांश सी ++ उपयोगकर्ताओं काफी खुश पढ़ने हैं std::string, std::vectorएक कच्चे देखकर वास्तव में, आदि, vectorबनाता है मुझे आश्चर्य है कि अगर यह है std::vectorया एक अलग उपयोगकर्ता परिभाषित vector

मैं हमेशा इस्तेमाल करने के खिलाफ हूं using namespace std;। यह वैश्विक नामस्थान में सभी प्रकार के नामों का आयात करता है और सभी प्रकार के गैर-स्पष्ट अस्पष्टताओं का कारण बन सकता है।

यहां कुछ सामान्य पहचानकर्ता हैं जो stdनामस्थान में हैं: गणना, सॉर्ट, ढूंढें, बराबर, रिवर्स। स्थानीय चर नामक countसाधन होने का मतलब है कि using namespace stdआप countइसके बजाय उपयोग करने में सक्षम नहीं होंगे std::count

एक अवांछित नाम संघर्ष का क्लासिक उदाहरण निम्नलिखित की तरह कुछ है। कल्पना कीजिए कि आप एक शुरुआती हैं और इसके बारे में नहीं जानते हैं std::count। कल्पना करें कि आप या तो किसी अन्य चीज का उपयोग कर रहे हैं <algorithm>या यह एक असंबद्ध हैडर द्वारा खींचा गया है।

#include <algorithm>
using namespace std;

int count = 0;

int increment()
{
    return ++count; // error, identifier count is ambiguous
}

त्रुटि आमतौर पर लंबी और अमित्र होती है क्योंकि std::countकुछ लंबे नेस्टेड प्रकारों के साथ एक टेम्पलेट होता है।

यह हालांकि ठीक है, क्योंकि std::countवैश्विक नामस्थान में जाता है और फ़ंक्शन गणना इसे छुपाती है।

#include <algorithm>
using namespace std;

int increment()
{
    static int count = 0;
    return ++count;
}

शायद थोड़ा आश्चर्य की बात है, यह ठीक है। एक घोषणात्मक दायरे में आयात किए गए पहचानकर्ता सामान्य नामस्थान में दिखाई देते हैं जो दोनों को परिभाषित करता है कि वे कहाँ परिभाषित किए गए हैं और वे कहाँ आयात किए गए हैं। दूसरे शब्दों में, वैश्विक नामस्थान के std::countरूप countमें दिखाई देता है , लेकिन केवल अंदर increment

#include <algorithm>

int increment()
{
    using namespace std;
    static int count = 0;
    return ++count;
}

और इसी तरह के कारणों के लिए, countयहाँ अस्पष्ट है। using namespace stdकारण नहीं है std::count, बाहरी छिपाने के countरूप में यह उम्मीद की जा सकती है। using namespaceशासन का मतलब है कि std::countलगता (में incrementसमारोह) जैसे कि यह वैश्विक क्षेत्र, यानी एक ही दायरे में घोषित किया गया था के रूप में int count = 0;है और इसलिए अस्पष्टता के कारण।

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}

21
लेकिन यह प्रकार soooo std :: उपसर्ग के बिना बहुत आसान!
xtofl

69
@xtofl: नहीं, यह नहीं है। टाइप करते समय पाँच अक्षर उतने प्रासंगिक नहीं हैं, लेकिन पढ़ते समय ये पाँच वर्ण बहुत प्रासंगिक हो सकते हैं। और पढ़ने में आसानी स्रोत कोड के लिए आसानी से अधिक मायने रखता है, क्योंकि कोड लिखित की तुलना में बहुत अधिक पढ़ा जाता है।
sbi

3
आप यह कह सकते हैं कि स्कोपिंग स्टेटमेंट स्कोप नियमों के साथ सही व्यवहार करता है।
मार्टिन यॉर्क

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

5
खैर, आश्चर्य है कि किसी ने भी इसके विकल्प के बारे में चर्चा नहीं की using std::xxx;। यह नामस्थान प्रदूषण नहीं करता है, लेखन कोड कम होगा और मुझे लगता copyहै कि इससे बहुत अधिक पढ़ा गया है std::copy
लीजेंड्स 2

41

मूल बातें छोड़कर (std जोड़ने के लिए :: सभी stl ऑब्जेक्ट्स / फ़ंक्शन का विरोध और संघर्ष की कम संभावना यदि आपके पास 'namespace std का उपयोग करके' नहीं है)

यह भी ध्यान देने योग्य है कि आपको कभी नहीं डालना चाहिए

using namespace std

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

कुछ मामलों में जैसे कि चीजों का इस्तेमाल करना बहुत फायदेमंद होता है

using std::swap

जैसे कि स्वैप का कोई विशेष संस्करण है, संकलक उसका उपयोग करेगा, अन्यथा वह वापस गिर जाएगा std::swap

यदि आप कॉल करते हैं std::swap, तो आप हमेशा मूल संस्करण का उपयोग करते हैं, जो कि अनुकूलित संस्करण को कॉल नहीं करेगा (यदि यह मौजूद है)।


10
उल्लेख करने के लिए +1 using std::swap(जो केवल एक चीज है जो मैं कभी उपयोग करता हूं)।
sbi

1
u n sप्रचार करने के लिए +1 । बस ध्यान दें कि यह सही ढंग से निर्मित हेडर में अपना रास्ता भी खराब कर सकता है: उन्हें सिर्फ एक दुष्ट हेडर के बाद शामिल करना होगा।
quamrana

1
लेकिन अगर आप एक को परिभाषित कर रहे swapया move(या hash, lessआदि) विशेषज्ञता, आप में है कि विशेषज्ञता डाल दिया जाना चाहिए namespace stdवैसे भी। उदाहरण के लिए:namespace std {template<> class hash<X> {public: size_t operator()(const X&) const};} class X: {friend size_t std::hash<X>::operator()(const X&)};
AJMansfield

28

सबसे पहले, कुछ शब्दावली:

  • उपयोग-घोषणा : using std::vector;
  • उपयोग-निर्देश : using namespace std;

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

using namespace std;

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

इसी तरह, यदि आप नेमस्पेस में विशिष्ट प्रकारों के लिए कुछ प्रयोग-घोषणाओं ( उपयोग-निर्देशों के बजाय ) के साथ प्राप्त कर सकते हैं std, तो कोई कारण नहीं है कि आपके पास वर्तमान नामस्थान में लाए गए उन नाममात्र के नाम नहीं होने चाहिए। एक ही टोकन से, मुझे लगता है कि यह पागल होगा और एक बहीखाता पद्धति में 25 या 30 का उपयोग करने की घोषणा होगी जब एक एकल-निर्देश का उपयोग चाल के रूप में भी किया जाएगा।

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

template< typename T >
void foo( T& x, T& y)
{
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

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

हर्ब सटर और आंद्रेई अलेक्जेंड्रेस्कु के पास यह कहना है कि "आइटम 59: हेडर फाइल में नेमस्पेस यूज़र्स न लिखें या उनकी किताब के एक #include से पहले, C ++ कोडिंग स्टैंडर्ड्स: 101 रूल्स, गाइडलाइन्स और बेस्ट प्रैक्टिस:

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

"द सी ++ प्रोग्रामिंग लैंग्वेज, थर्ड एडिशन" में स्ट्रूपस्ट्रैप को अक्सर कहा जाता है, "ग्लोबल नेमस्पेस को प्रदूषित न करें"। वह वास्तव में कहता है कि (C.14 [15]), लेकिन अध्याय C.10.1 को संदर्भित करता है जहां वह कहता है:

एक प्रयोग-घोषणा में एक नाम स्थानीय दायरे में जोड़ा जाता है। एक का उपयोग-निर्देश नहीं करता है; यह केवल उस दायरे में सुलभ नामों को प्रस्तुत करता है जिनमें उन्हें घोषित किया गया था। उदाहरण के लिए:

namespaceX {
    int i , j , k ;
}

int k ;
void f1()
{
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

    X::k ++; // X’s k
}

void f2()
{
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

    i++;
    j++; // X::j
    k++; // X::k
}

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

के लिए अस्पष्टता त्रुटि नोट k++में f1()। वैश्विक दायरे में सुलभ किए गए नामस्थानों से नामों पर वैश्विक नामों को वरीयता नहीं दी जाती है। यह आकस्मिक नाम के टकराव के खिलाफ महत्वपूर्ण सुरक्षा प्रदान करता है, और - महत्वपूर्ण रूप से - यह सुनिश्चित करता है कि वैश्विक नामों को प्रदूषित करने से कोई लाभ प्राप्त न हो।

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

...

मुझे पारंपरिक सी और सी ++ कार्यक्रमों की तुलना में नामस्थानों का उपयोग करके नए कार्यक्रमों में वैश्विक नामों के उपयोग में एक क्रांतिकारी कमी देखने की उम्मीद है। नाम स्थान के नियमों को विशेष रूप से किसी ऐसे व्यक्ति पर वैश्विक नामों के '' आलसी '' उपयोगकर्ता को कोई लाभ नहीं देने के लिए तैयार किया गया था जो इस बात का ध्यान रखता है कि वैश्विक दायरे को प्रदूषित न करें।

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

ध्यान दें कि एक नाम- stdस्थान में उपलब्ध नाम-निर्देश एक प्रयोग-निर्देश के उचित उपयोग के साथ एक गुंजाइश को उपलब्ध कराया गया है (निर्देश के बाद रखकर #includes) वैश्विक नाम स्थान को प्रदूषित नहीं करता है । यह सिर्फ उन नामों को आसानी से उपलब्ध करा रहा है, और झड़पों के खिलाफ निरंतर सुरक्षा के साथ।


अपने अंतिम बिंदु के संबंध में: जावा और सी # में बहुत अधिक नेचर नामस्थान हैं। यदि बीसीएल में सब कुछ सिस्टम में रहता था, तो "सिस्टम का उपयोग करना" "नेमस्पेस स्टड का उपयोग करने" के रूप में बहुत परेशानी का कारण होगा।
जेफ हार्डी

लेकिन जावा और सी # प्रोग्राम जो मैं देख रहा हूं, वे आमतौर पर उन सभी नामस्थानों में लाते हैं जो वे उपयोग करते हैं - न कि केवल "सिस्टम" (या इसके समकक्ष)। इसलिए एक ही निर्देशन का उपयोग करने के बजाय, जो उपयोग किए गए सभी नामों को लाता है, ऐसे 5 या 10 हैं जो कमोबेश एक ही काम करते हैं। इसके अलावा, "नाम स्थान std का उपयोग कर रहा है?" वास्तव में बहुत परेशानी का कारण?
माइकल बूर

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

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

1
@AProgrammer: आप कहते हैं, "सूची एक लिस्प दुभाषिया में सूची की पहचान के लिए एक प्राकृतिक पहचानकर्ता है" - लेकिन " using namespace std;" निर्देश होने से आप अपने प्राकृतिक पहचानकर्ता को घोषित करने से नहीं रोक सकते ' list' - यह सिर्फ इतना है कि यदि आप करते हैं, तो आप नहीं कर सकते लंबे समय तक std::listयह योग्यता के बिना उपयोग करें । अगर कोई using namespace std;निर्देश नहीं है तो यह अलग नहीं है । या क्या मैं कुछ न कुछ भूल रहा हूं?
माइकल बूर

17

हेडर फ़ाइल में वैश्विक स्कोप पर नेमस्पेस का उपयोग कभी न करें। यह संघर्ष का कारण बन सकता है और फ़ाइल के प्रभारी व्यक्ति को जहां विरोध दिखाई देता है, उसका कारण पर कोई नियंत्रण नहीं है।

कार्यान्वयन फ़ाइल में, विकल्प बहुत कम अच्छी तरह से कटे हुए हैं।

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

  • Std :: name का उपयोग करके डालना; अज्ञात प्रतीकों के आयात के जोखिम के बिना लेखन की सादगी का लाभ है। लागत यह है कि आपको सभी वांछित प्रतीकों को स्पष्ट रूप से आयात करना होगा।

  • स्पष्ट रूप से क्वालीफाइंग थोड़ा अव्यवस्था जोड़ते हैं, लेकिन मुझे लगता है कि यह कुछ अभ्यास की कम परेशानी है।

मेरी परियोजना में, मैं सभी नामों के लिए स्पष्ट योग्यता का उपयोग करता हूं, मैं std :: name का उपयोग करके स्वीकार करता हूं, मैं नेमस्पेस std का उपयोग करने के खिलाफ लड़ता हूं (हमारे पास एक लिस्प दुभाषिया है जिसकी अपनी सूची प्रकार है और इसलिए संघर्ष एक निश्चित चीज है)।

अन्य नामस्थानों के लिए, आपको उपयोग किए गए नामकरण सम्मेलनों को भी ध्यान में रखना होगा। मुझे एक प्रोजेक्ट का पता है, जो नामों पर नामस्थान (संस्करण के लिए) और उपसर्ग का उपयोग करता है। using namespace Xतब तक ऐसा करना लगभग बिना किसी जोखिम के होता है और ऐसा नहीं करने से बेवकूफ़ दिखने वाला कोड होता है PrefixNS::pfxMyFunction(...)

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


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

टिप्पणियों में, माइकल बूर आश्चर्य करता है कि क्या वास्तविक दुनिया में संघर्ष होते हैं। यहाँ एक वास्तविक लाइव छूट है। हमारे पास एक विस्तार भाषा है जो एक लिस्प बोली है। हमारे दुभाषिया में एक फ़ाइल शामिल है, जिसमें lisp.h सम्‍मिलित है

typedef struct list {} list;

हमें कुछ कोड को एकीकृत करना और अनुकूलित करना था (जो मैं "इंजन" नाम दूंगा) जो इस तरह दिखता था:

#include <list>
...
using std::list;
...
void foo(list const&) {}

तो हम इस तरह से संशोधित:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

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


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

1
मुझे लगता है कि टाइपिंग एसटीडी :: स्पष्टता के लिए भुगतान करने के लिए एक छोटी सी कीमत है
पैगोरिकार्डो

4
@ तिरंगा: दूसरी ओर, मुझे लगता है कि std :: सभी जगह दिखाओ अनावश्यक दृश्य अव्यवस्था है।
माइकल ब्यूर

1
@ माइकल: आप अपने पैसे का भुगतान करते हैं और आप अपनी पसंद बनाते हैं!
पैगोरिकार्डो

2
आपके द्वारा चलाए गए समस्या के विवरण को जोड़ने के लिए समय निकालने के लिए धन्यवाद।
माइकल बूर

4

यदि आपके पास अपने कोड में std और अन्य पुस्तकालयों के साथ नाम संघर्ष का जोखिम नहीं है जिसका आप उपयोग कर सकते हैं:

using namespace std;

लेकिन अगर आप चाहते हैं कि आपको प्रलेखन के लिए अपने कोड की निर्भरता का ठीक-ठीक पता चल जाए या फिर नाम संघर्ष का जोखिम हो तो दूसरे तरीके का उपयोग करें:

using std::string;
using std::cout;

तीसरा समाधान, इन समाधानों का उपयोग न करें और std :: कोड में प्रत्येक उपयोग से पहले आपको और अधिक सुरक्षा प्रदान करता है लेकिन, शायद कोड में थोड़ा भारीपन ...


4

दोनों

using std::string;

तथा

using namespace std;

वैश्विक नामस्थान पर कुछ प्रतीक (एक या बहुत सारे) जोड़ें। और वैश्विक नेमस्पेस में प्रतीकों को जोड़ना कुछ ऐसी चीजें हैं जो आपको हेडर फाइलों में कभी नहीं करनी चाहिए । आपके पास कोई नियंत्रण नहीं है जो आपके हेडर को शामिल करेगा, बहुत सारे हेडर हैं जिनमें अन्य हेडर शामिल हैं (और हेडर जिसमें हेडर शामिल हैं जिसमें हेडर और इतने पर शामिल हैं ...)।

कार्यान्वयन (.cpp) फ़ाइलों में यह आपके ऊपर है (केवल # सभी निर्देशों के बाद इसे करना याद रखें )। आप इस विशिष्ट फ़ाइल में केवल कोड को तोड़ सकते हैं, इसलिए नाम संघर्ष के कारण का प्रबंधन और पता लगाना आसान है। यदि आप इंडेंटिफायर से पहले std :: (या किसी अन्य उपसर्ग का उपयोग करना चाहते हैं, तो आपके प्रोजेक्ट में कई नाम स्थान हो सकते हैं) यह ठीक है। यदि आप वैश्विक नेमस्पेस का उपयोग करने वाले पहचानकर्ता जोड़ना पसंद करते हैं, तो यह ठीक है। यदि आप पूरे नामपट्ट को अपने सिर पर लाना चाहते हैं :-), यह आपके ऊपर है। जबकि प्रभाव एकल संकलन इकाई तक सीमित हैं, यह स्वीकार्य है।


3

मेरे लिए, मैं ::संभव होने पर उपयोग करना पसंद करता हूं ।

std::list<int> iList;

मुझे लिखने से नफरत है:

for(std::list<int>::iterator i = iList.begin(); i != iList.end(); i++)
{
    //
}

उम्मीद है, C ++ 0x के साथ मैं यह लिखूंगा:

for(auto i = iList.begin(); i != iList.end(); i++)
{
    //
}

यदि नाम स्थान बहुत लंबा है,

namespace dir = boost::filesystem;

dir::directory_iterator file("e:/boost");
dir::directory_iterator end;

for( ; file != end; file++)
{
    if(dir::is_directory(*file))
        std::cout << *file << std::endl;
}

@ आरा: नेमस्पेस dir = boost :: filesystem; मुझे लगता है कि यह एक उपनाम है?
पैगोरिकार्डो

@ अंपोरिकार्डो: हाँ, यह क्या है।
sbi

2
Iterators के साथ वेतन वृद्धि की जानी चाहिए ++i, i++इसलिए नहीं कि यदि इसे परिभाषित भी किया जाता है, तो यह इटरेटर की एक अनावश्यक अस्थायी प्रतिलिपि बनाता है।
फेलिक्स डॉम्बेक जूल

2

आपको using namespace stdकिसी शीर्ष लेख में नाम स्थान के दायरे में कभी नहीं होना चाहिए । इसके अलावा, मुझे लगता है कि अधिकांश प्रोग्रामर आश्चर्य करेंगे जब वे देखते हैं vectorया stringबिना std::, तो मुझे लगता है कि using namespace stdबेहतर नहीं है। इसके लिए मैं तर्क देता हूं कि कभी नहीं using namespace std

यदि आपको ऐसा लगता है कि आपको घोषणाओं का उपयोग करके स्थानीय जोड़ना होगा using std::vector। लेकिन अपने आप से पूछें: इस लायक क्या है? कोड की एक पंक्ति एक बार (शायद दो बार) लिखी जाती है, लेकिन यह दस, सौ या हजार बार पढ़ी जाती है। कोड को पढ़ने के प्रयास की तुलना में सहेजे हुए टाइपिंग प्रयास को एक घोषणा या निर्देशन के साथ जोड़ा जाना मामूली है।

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

मैंने पाया है कि आमतौर पर, जो लोग प्रतिबंध का विरोध करते हैं, उन्होंने usingआमतौर पर एक परियोजना के लिए कोशिश नहीं की है। जिन्होंने कोशिश की है, वे अक्सर बहुत कम समय के बाद निर्देश / घोषणाओं का उपयोग करने से बेहतर पाते हैं।

नोट: एकमात्र अपवाद using std::swapजो आवश्यक है (विशेष रूप से जेनेरिक कोड में) swap()उस के अधिभार को लेने के लिए stdनामस्थान में नहीं डाला जा सकता है (क्योंकि हमें stdइस नामस्थान में कार्यों के ओवरलोड डालने की अनुमति नहीं है )।


3
एसटीडी का एक विशेषज्ञता :: स्वैप एक पूर्ण विशेषज्ञता होगी - आप आंशिक रूप से फ़ंक्शन टेम्पलेट्स को विशेषज्ञ नहीं कर सकते। किसी भी कार्यक्रम को किसी भी मानक पुस्तकालय टेम्पलेट को आंशिक रूप से विशेषज्ञ करने की अनुमति है जब तक कि विशेषज्ञता उपयोगकर्ता-परिभाषित प्रकार पर निर्भर करती है।
सीबी बेली

@Charles: हां, आप सही कह रहे हैं, बेशक, यह एफटीपीएस नहीं है। और मैं कर सकते हैं विशेषज्ञ भीतर टेम्पलेट्स std, लेकिन ओवरलोड नहीं। उस मंथन के लिए क्षमा करें। मैं पोस्ट ठीक कर दूंगा।
sbi

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


1
@ एसएसबी: नहीं, यह उद्देश्य नहीं है। यह इस बात पर निर्भर करता है कि क्या आपको लगता है कि std :: मददगार है या अव्यवस्थित है। अधिक अव्यवस्था -> कम स्पष्टता।
जोशुआ रिचर्डसन

2

फ़ंक्शन हस्ताक्षरों के भ्रम और प्रदूषण को रोकने के लिए नाम स्थान कोड को समाहित रखता है ।

यहाँ उचित नामस्थान उपयोग का एक पूर्ण और प्रलेखित डेमो है :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see /programming/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

आउटपुट:

Our log: 42
Standard log: 1.43508

1

using namespace stdstdवर्तमान में नाम स्थान की सामग्री को आयात करता है । इस प्रकार, लाभ यह है कि आपको std::उस नाम स्थान के सभी कार्यों के सामने टाइप नहीं करना पड़ेगा । हालाँकि, ऐसा हो सकता है कि आपके पास अलग नामस्थान हों जिनमें एक ही नाम के कार्य हों। इस प्रकार, आप अपने इच्छित फोन को समाप्त नहीं कर सकते हैं।

मैन्युअल रूप से निर्दिष्ट करना कि आप किन चीज़ों को आयात करना चाहते हैं, ऐसा stdहोने से रोकता है, लेकिन परिणामस्वरूप आपकी फ़ाइल की शुरुआत में लंबी सूची का उपयोग हो सकता है, जिसे कुछ डेवलपर बदसूरत पाएंगे;)

व्यक्तिगत रूप से, मैं हर बार किसी फ़ंक्शन का उपयोग करने वाले नाम स्थान को निर्दिष्ट करने को प्राथमिकता देता हूं, सिवाय इसके कि जब नाम स्थान बहुत लंबा हो, तो उस स्थिति में मैं फ़ाइल की शुरुआत में कुछ का उपयोग करता हूं।

EDIT: जैसा कि एक अन्य जवाब में कहा गया है, आपको कभी भी using namespaceहेडर फाइल में नहीं डालना चाहिए , क्योंकि यह इस हेडर सहित सभी फाइलों को प्रचारित करेगा और इस तरह अवांछित व्यवहार उत्पन्न कर सकता है।

EDIT2: चार्ल्स टिप्पणी के लिए धन्यवाद, मेरे जवाब को सही किया।


2
using namespace std;stdवैश्विक नामस्थान में नामस्थान की सामग्री आयात करता है । यह डिफ़ॉल्ट नाम स्थान नहीं बदलता है। वैश्विक नामस्थान में कुछ को परिभाषित करने के बाद using namespace stdजादुई रूप से इसे stdनामस्थान में नहीं रखा जा सकता है ।
सीबी बेली

क्षमा करें, यह मेरा मतलब नहीं था। इसे इंगित करने के लिए धन्यवाद, मैं अपना उत्तर सही करूंगा।
वूकाई

1
दोस्तो, प्रतिक्रियाओं के लिए धन्यवाद। ऐसा प्रतीत होता है कि, सामान्य रूप से, यह 'नेमस्पेस std का उपयोग' नहीं करने और संभावित अस्पष्टता पैदा करने से बचने के लिए सुरक्षित है। 'Std :: xxx' का उपयोग करते हुए संतुलन पर स्रोत फ़ाइल की शुरुआत में विभिन्न कार्यों की एक सूची घोषित करने की तुलना में मुझसे अधिक अपील की जाती है क्योंकि यह स्पष्ट रूप से योग्य है कि किसी का इरादा क्या है।
पैगोरिकार्डो

1
उद्धरण (जब नाम स्थान बहुत लंबा है) को छोड़कर। आप वहाँ मदद करने के लिए नाम स्थान का उपयोग कर सकते हैं। 'नामस्थान Rv1 = थोर :: XML :: XPath :: नियम :: लाइट :: वर्जन 1?' नोट उपनामों और दोनों नियमों का पालन करते हुए;
मार्टिन यॉर्क

0

जावा में बहुत पसंद है जहाँ आप या तो java.util का उपयोग कर सकते हैं। * या बस प्रत्येक वर्ग का व्यक्तिगत रूप से चयन करें, यह शैली पर निर्भर करता है। ध्यान दें कि आप using namespace stdअपनी फ़ाइल / विस्तृत दायरे की शुरुआत में एक नहीं चाहते हैं क्योंकि आप नेमस्पेस को प्रदूषित करेंगे और संभवतः नाम स्थान की बात को पराजित करते हुए क्लैश होंगे। लेकिन अगर आपके पास एक फ़ंक्शन है जो बहुत सारे एसटीएल का उपयोग करता है, तो यह आपके तर्क में उपसर्ग सिंटैक्स की गड़बड़ी के लिए कोड को बंद कर देता है और आपको संभवतः using namespace std( या तो विभिन्न वर्गों का उपयोग करते समय) या व्यक्तिगत usingएस (कुछ का उपयोग करते समय ) का उपयोग करने पर विचार करना चाहिए कक्षाएं अक्सर)।


0

यह चर्चा तब तक जीवित रहने वाली है जब तक आप जिस आईडीई के साथ काम करते हैं, वह आपके द्वारा बताई गई सटीक जानकारी को दिखाने या छिपाने के लिए पर्याप्त लचीला नहीं है।

ऐसा इसलिए है क्योंकि आप चाहते हैं कि आपका कोड कैसा दिखे, यह हाथ में काम पर निर्भर करता है।

अपना स्रोत कोड बनाते समय, मैं वास्तव में यह देखना पसंद करता हूं कि मैं किस वर्ग का उपयोग कर रहा हूं: यह है std::string, या BuzFlox::Obs::stringवर्ग?

नियंत्रण प्रवाह को डिजाइन करते समय, मैं चर के प्रकारों में भी दिलचस्पी नहीं रखता हूं, लेकिन मैं if's और while' s ' और ' s ' पर ध्यान केंद्रित करना चाहता हूं continue

तो यह मेरी सलाह है:

आपके कोड के दर्शकों और आपके उपकरणों की शक्ति के आधार पर, उस तरीके को चुनें जो या तो सबसे आसान पढ़ता है, या अधिकांश जानकारी देता है।


0

इसे ठीक करने के कई तरीके हैं।

पहला: जैसा आपने किया उसका उपयोग करें।

दूसरा: करते हैं namespace S = std;, 2 चर को कम करने।

तीसरा: उपयोग static

चौथा: उपयोग करने वाले नामों का stdउपयोग न करें ।


-1

प्रत्येक का भला - बुरा क्या है

एसटीडी को छोड़ने का एकमात्र कारण :: यह है कि आप सिद्धांत रूप में, सभी एसटीएल कार्यों को स्वयं लागू कर सकते हैं। तब आपके कार्यों को कोड को बदले बिना std :: वेक्टर से my :: वेक्टर का उपयोग करने से रोका जा सकता है।


नाम स्थान वास्तव में अलग, लेकिन समकक्ष, कार्यक्षमता के साथ नामों के प्रतिस्थापन की अनुमति देने के लिए डिज़ाइन नहीं किए गए हैं। वे अनपेक्षित नाम की गड़बड़ी को रोकने के लिए डिज़ाइन किए गए हैं।
माइकल ब्यूर

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

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

मुझे लगता है कि "उपयोग करना" का उद्देश्य आपको 3 अक्षरों को बचाने के बजाय वैकल्पिक कार्यान्वयन पर स्विच करने की अनुमति देना था। मुझे "std :: Foo" का उपयोग करना पसंद है क्योंकि यह प्रोग्रामर को एक अनुबंध के रूप में कार्य करता है कि मैं सामान्य फू का उपयोग कर रहा हूं और उन्हें जांचने की आवश्यकता नहीं है। मैं मानता हूं कि मुझे "com.microsoft.visual-studio.standard-library.numbers.int foo" टाइप नहीं करना होगा, एसटीएल में कुछ इटैलर घोषणाएं इस तरह से मिलती हैं। पायथन आपको मॉड्यूल से कार्यों के सजाया या अघोषित सेट में खींचने की अनुमति देने का एक अच्छा काम करता है।
मार्टिन बेकेट

-1

उदाहरण के लिए क्यों नहीं

typedef std::vector<int> ints_t;
ints_t ints1;
....
ints_t ints2;

बेवजह की जगह

std::vector<int> ints1;
...
std::vector<int> ints2;

मुझे लगता है कि कोडिंग के लिए बहुत अधिक पठनीय और इसके मानक हैं।

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

void getHistorgram(std::vector<unsigned int>&, std::vector<unsigned int>&);

वापसी का मूल्य क्या है?

इसके बजाय कैसे?

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.