C ++ में `using` का उपयोग करें या इससे बचें?


17

ADL की वजह से अलग-अलग शब्दार्थों को मजबूत करना, मुझे आम तौर पर कैसे उपयोग करना चाहिए using, और क्यों? क्या यह स्थिति-निर्भर (जैसे हेडर जो #included बनाम सोर्स फाइल होगा जो नहीं होगा)?

इसके अलावा, मुझे पसंद करना चाहिए ::std::या std::?

  1. नाम स्थान-स्तर using namespace:

    using namespace std;
    
    pair<string::const_iterator, string::const_iterator>
    f(const string &s) {
        return make_pair(s.begin(), s.end());
    }
  2. पूरी तरह से स्पष्ट होना:

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        return std::make_pair(s.begin(), s.end());
    }
  3. नाम-स्तर का उपयोग-घोषणाएँ:

    using std::pair;
    using std::string;
    
    pair<string::const_iterator, string::const_iterator>
    f(const string &s) {
        return make_pair(s.begin(), s.end());
    }
  4. समारोह-स्थानीय उपयोग-घोषणाएँ:

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        using std::make_pair;
        return make_pair(s.begin(), s.end());
    }
  5. समारोह-स्थानीय using namespace:

    std::pair<std::string::const_iterator, std::string::const_iterator>
    f(const std::string &s) {
        using namespace std;
        return make_pair(s.begin(), s.end());
    }
  6. कुछ और?

यह पूर्व-सी ++ 14 मान रहा है, और इस प्रकार कोई रिटर्न-प्रकार-कटौती का उपयोग नहीं कर रहा है auto


2
शुरुआती बिंदु के लिए stackoverflow.com/questions/1265039/use-std-namespace देखें ।
एपीग्रामग्राम

@AProgrammer: आह, लिंक के लिए धन्यवाद, जो मेरे सवाल का हिस्सा है। :) फिर भी ::std::बनाम के बारे में सोच रहा था std::
user541686

4
मैं stdहालांकि दूसरे के बिना उपयोग कर रहा हूँ । कोई व्यक्ति एक std नाम स्थान को परिभाषित करने के लिए मुसीबत पूछ रहा है (और शायद इसका फायदा उठाने के लिए खोज कर रहा है जो कि ज्यादातर लोग उपयोग कर रहे हैं stdऔर नहीं ::std)।
एपीग्रामग्राम

जवाबों:


25

usingहेडर में उपयोग करने से बचें , क्योंकि यह नामस्थान के उद्देश्य को तोड़ता है।

स्रोत फ़ाइलों में इसका उपयोग करना ठीक है, लेकिन मैं अभी भी कुछ मामलों में (उदाहरण के लिए using std) इससे बचूंगा ।

हालाँकि अगर आपको नेस्टस्पेस नाम दिया गया है, तो यह ठीक है:

namespace A {
namespace B {
namespace C {
class s;
} // C
} // B
namespace D{
using B::C::s;
} // D
} // A

6
+1 यह आश्चर्यजनक है कि कितने ट्यूटोरियल और कॉलेज पाठ्यक्रम आपको यह बताने के लिए usingकीवर्ड का उपयोग करने के लिए कहते हैं कि नामस्थान का उपयोग शुरू करने के लिए क्यों किया जाता है।
जेफरी स्वीनी

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

Typedef std :: स्ट्रिंग sstring जैसा कुछ होगा; एक विकल्प हो?
जियोर्जियो

1
@ कॉलेन: ये ख़राब आत्माएं using std::coutऔर दोस्त इस्तेमाल कर सकते हैं , लेकिन ऐसा नहीं है coutकि पहले से ही एक बहुत लंबा नाम है।
बेंजामिन बैनियर

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

11

स्रोत फ़ाइल में एक उपयोग स्टेटमेंट डालते समय, कृपया, केवल उन चीज़ों में खींचें जिनकी आपको ज़रूरत है। उदाहरण के लिए:

using std::string;
using std::ostringstream;

यहां मुद्दा यह है कि यदि आप ऐसा करते हैं

using namespace std;

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


वैकल्पिक रूप से, आप using namespaceसमस्या से बचते हुए, केवल एक कार्यक्षेत्र में हो सकते हैं ।
तमसे सजेले

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

जबकि C ++ वास्तव में किसी को फ़ंक्शन स्तर पर प्रकार घोषित करने की अनुमति देता है, यह एक सामान्य बात नहीं है; इसके अलावा, संभावित नाम की झड़प कंपाइलर आउटपुट से स्पॉट करना आसान है (लेकिन आप सही हैं कि यह उन्हें रोकता नहीं है)।
तमसे सजेलेई

2

जैसा कि VJovic इंगित करता है, usingहेडर फ़ाइल में उपयोग न करें । usingहेडर फ़ाइल वर्तमान संकलन इकाई (.cpp फ़ाइल) को उन तरीकों से प्रभावित करती है जिनसे स्रोत फ़ाइल अपेक्षा नहीं कर सकती है।

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


2
एक व्यावहारिक चिंता के रूप में, जब तक कि आपका कोड आमतौर पर उपयोग किए जाने वाले नामों से आगे नहीं निकलता, मैं बहुत अधिक बल्कि हर वस्तु using namespace JoystickModuleसे JoystickModule::जुड़ी एक .cpp फ़ाइल की शुरुआत में देखूंगा ।
एलेक्स पी।

@AlexP: बिल्कुल यही है कि मैं यह कैसे करते हैं। usingअपने स्वयं के नामस्थान के लिए एक कथन जो मैं वर्तमान में काम कर रहा हूं और बाकी सभी नाम नाम स्थान पर हैं।
बेंजामिन क्लोस्टर

मुझे "नामस्थान से विशिष्ट प्रतीकों का उपयोग" पर विस्तार से बताना चाहिए। प्रत्येक उपयोग पर प्रत्येक प्रतीक को उपसर्ग करने के बजाय, जो पठनीयता के साथ मदद नहीं करता है, मैं स्पष्ट प्रतीक उत्थापन का उपयोग करना पसंद करता हूं। using SomeNameSpace::SomeSymbol। यह नामपट्टी से हर प्रतीक को मौजूदा दायरे में ले जाने से बचता है।
बिल डोर

0

हेडर्स usingमें लिखना सभी प्रकार के गंदे और असंभव को डिबग करने का सबसे अच्छा तरीका है । है यह करते हैं।

using namespace XYZस्रोत फ़ाइल में लिखना थोड़ा बेहतर है, लेकिन फिर भी आप अनगिनत सिरदर्द पैदा कर सकते हैं। सुरक्षित तरीका यह है कि आप जो भी उपयोग कर रहे हैं उसे स्पष्ट रूप से बताएं using Foo::Bar

मान लें कि आपके पास निम्नलिखित के साथ Bar.cpp है:

//Bar.cpp
using namespace Foo;
namespace
{
    double increment(double v) { return (v + 1); }
}

void Bar::someFunction()
{
    //...
    int currentIndex = 0;
    int nextIndex = increment(currentIndex);
    //...
}

फ़ंक्शन ने ठीक काम किया, जब तक कि एक दिन - प्रासंगिक कक्षाओं में किसी भी कोड में बदलाव के बिना प्रतीत नहीं होता - इसका व्यवहार बदल गया: अचानक currentIndexहमेशा एक से दूर होने लगता है । हाल के परिवर्तनों के माध्यम से खुदाई करने पर आपको कोड से संबंधित दूरस्थ रूप से कोई परिवर्तन नहीं मिलता है।

अंततः आप कारण का पता लगाते हैं:
आप (अप्रत्यक्ष रूप से) Foo.hकहीं न कहीं शामिल हैं । फू नेमस्पेस के लिए फाइलों में एक नया फ़ंक्शन जोड़ा गया था:

//Foo.h
namespace Foo
{
    //...
    int& increment(int& v) { v += 1; return v; };
    //...
}

जो increment(int)आपके फ़ंक्शन की तुलना में एक बेहतर रूप से बेहतर मैच है increment(double)- इसलिए अब Foo::increment()फ़ंक्शन को Bar::someFunction()इसके बजाय कहा जाता है । ओह।

(और अगर आप usingहेडर्स में लिखें कि आपके पेड़ में कहीं भीusing namespace Foo बहुत अच्छी तरह से हो सकता है ...)

इसलिए ... हेडर में कोई भी लिखें using, और using namespaceस्रोत फ़ाइलों में लिखने से भी सावधान रहें ।

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