2008-12-10 13 views
158

मैं अभी एक नई सी ++ सॉफ्टवेयर प्रोजेक्ट में शामिल हो गया हूं और मैं डिजाइन को समझने की कोशिश कर रहा हूं। परियोजना अज्ञात नामस्थानों का लगातार उपयोग करता है। उदाहरण के लिए, कुछ इस तरह एक वर्ग परिभाषा फ़ाइल में हो सकता है:नामित नामस्थान क्यों उपयोग किए जाते हैं और उनके लाभ क्या हैं?

// newusertype.cc 
namespace { 
    const int SIZE_OF_ARRAY_X; 
    const int SIZE_OF_ARRAY_Y; 
    bool getState(userType*,otherUserType*); 
} 

newusertype::newusertype(...) {... 

क्या डिजाइन संबंधी कि एक एक अनाम नाम स्थान का उपयोग करने के कारण हो सकता है कर रहे हैं? फायदे और नुकसान क्या हैं?

उत्तर

148

(निम्नलिखित में, स्ट्राइक-थ्रू चीजें ऐसी चीजें हैं जो अब सी ++ 11 पर लागू नहीं होती हैं, लेकिन सी ++ 03 पर लागू होती हैं। सी ++ 11 अब लगभग कोई अंतर नहीं बनाता है (यदि वहां है हैं, वे सिर्फ भाषा वकील मतभेद हैं जिन्हें मैं याद नहीं कर सकता)।)।

अनाम नाम एक पहचानकर्ता प्रभावी ढंग से अनुवाद इकाई स्थानीय बनाने के लिए उपयोगिता है। वे के रूप में यदि आप एक नाम स्थान के लिए प्रति अनुवाद इकाई एक अद्वितीय नाम का चयन करेंगे व्यवहार करते हैं:

namespace unique { /* empty */ } 
using namespace unique; 
namespace unique { /* namespace body. stuff in here */ } 

खाली शरीर का उपयोग कर अतिरिक्त कदम, महत्वपूर्ण है तो आप पहले से ही ::name तरह पहचानकर्ता के नाम स्थान शरीर के भीतर का उल्लेख कर सकते परिभाषित कर रहे हैं कि उस नामस्थान में, क्योंकि उपयोग निर्देश पहले से ही हुआ था।

इसका मतलब है आप नि: शुल्क कार्य (उदाहरण के लिए) help कहा जाता है कि कई अनुवाद इकाइयों में मौजूद कर सकते हैं हो सकता है, और वे अपने अद्वितीय नाम स्थान वे कर रहे हैं की वजह से, लिंक समय में टकराव नहीं होगा बाद से वे सभी एक अद्वितीय नाम मिला में। प्रभाव सी में प्रयुक्त static कीवर्ड का उपयोग करने के लगभग समान है जिसे आप पहचानकर्ताओं की घोषणा में डाल सकते हैं। static उस तरीके से उपयोग किया जाता है जिसे सी ++ में बहिष्कृत किया जाता है, क्योंकि अनाम नामस्थान एक बेहतर विकल्प हैं, जो एक प्रकार का अनुवाद इकाई स्थानीय भी बना सकते हैं।

namespace { int a1; } 
static int a2; 

दोनों a के अनुवाद इकाई स्थानीय कर रहे हैं और कड़ी समय में टकराव नहीं होगा। लेकिन अंतर यह है कि अज्ञात नेमस्पेस में a1 बस एक अद्वितीय नाम प्राप्त करता है। यह अभी भी बाहरी जुड़ाव है और इसे बनाए जा रहे ऑब्जेक्ट फ़ाइल की प्रतीक तालिका में निर्यात किया जा सकता है।

template<int * ptr> struct sample { }; 

// OK - a1 has external linkage 
sample<&a1> s1; 
// NOT OK - translation unit locality is done by giving a2 internal linkage. 
sample<&a2> s2; 

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

आउ-कंप्यूटिंग `Why is an unnamed namespace used instead of static? पर उत्कृष्ट लेख पढ़ें।

+3

क्या यह वास्तव में "अभी भी बाहरी संबंध है"? 3.5/4 ऐसा सुझाव देता है कि अज्ञात नेमस्पेस में सब कुछ आंतरिक जुड़ाव हो जाता है ...? –

+2

@kerr no मेरा उत्तर पुराना है। मुझे इसे सी ++ 11 के लिए अपडेट करने की आवश्यकता होगी। धन्यवाद –

+0

@ जोहान्सचैब-लिटब: धन्यवाद। मुझे लगता है कि मैं जाकर [इस विषय पर मेरा उत्तर] (http://stackoverflow.com/a/12539201/596781) तो हटाने होंगे, क्योंकि यह एकमुश्त गलत है। –

48

एक गुमनाम नाम स्थान में कुछ होने का मतलब है कि यह इस translation unit के लिए स्थानीय (.cpp फ़ाइल और सभी इसकी भी शामिल है) इसका मतलब है कि अगर एक ही नाम के साथ एक और प्रतीक परिभाषित किया गया है कहीं और वहाँ (ओडीआर) का उल्लंघन नहीं होगा ।

यह स्थैतिक वैश्विक परिवर्तनीय या स्थैतिक फ़ंक्शन होने के सी तरीके के समान है लेकिन इसका उपयोग कक्षा परिभाषाओं के लिए भी किया जा सकता है (और C12+ में static के बजाय उपयोग किया जाना चाहिए)।

उसी फ़ाइल में सभी अज्ञात नामस्थानों को समान नामस्थान के रूप में माना जाता है और विभिन्न फ़ाइलों में सभी अनाम नामस्थान अलग-अलग होते हैं।

namespace __unique_compiler_generated_identifer0x42 { 
    ... 
} 
using namespace __unique_compiler_generated_identifer0x42; 
+0

अनुवाद इकाई का वर्णन करने के लिए धन्यवाद। – nirvanaswap

8

एक अनाम नाम स्थान संलग्न चर, कार्यों, वर्ग, आदि केवल उस फ़ाइल के अंदर उपलब्ध बनाता है: एक अनाम नाम स्थान के बराबर है। आपके उदाहरण में यह वैश्विक चर से बचने का एक तरीका है। कोई रनटाइम या संकलन समय प्रदर्शन अंतर नहीं है।

"क्या मैं इस चर, फ़ंक्शन, कक्षा इत्यादि को सार्वजनिक या निजी होना चाहता हूं" से बहुत अधिक लाभ या नुकसान नहीं है? "

+1

प्रदर्शन अंतर हो सकते हैं - मेरा उत्तर यहां देखें। यह संकलक को कोड को बेहतर अनुकूलित करने की अनुमति देता है। – xioxox

+1

आपके पास एक बिंदु है; कम से कम सी ++ आज तक है। हालांकि, सी ++ 98/सी ++ 03 आवश्यक चीजों को टेम्पलेट तर्क के रूप में उपयोग करने के लिए बाहरी संबंध है। चूंकि गुमनाम नामस्थान में बातें टेम्पलेट तर्क के रूप में उपलब्ध हैं, वे भले ही कोई रास्ता नहीं फ़ाइल बाहर से उन्हें करने के लिए था बाहरी लिंकेज (कम से कम में पूर्व सी ++ 11) होगा। मुझे लगता है कि उस पर झगड़ा करने की कुछ क्षमता हो सकती है, क्योंकि मानक केवल इतना आवश्यक है कि चीजें कार्य करें जैसे नियम लागू किए गए हों; और कभी-कभी नियमों को लागू किए बिना ऐसा करना संभव होता है। –

11

उदाहरण से पता चलता है कि इस परियोजना में लोगों को आप में शामिल हो गए गुमनाम नामस्थान :)

namespace { 
    const int SIZE_OF_ARRAY_X; 
    const int SIZE_OF_ARRAY_Y; 

ये एक गुमनाम नाम स्थान में होने की जरूरत नहीं है समझ में नहीं आता, क्योंकि const वस्तु पहले से ही स्थिर संबंध है और इसलिए संभवतः एक ही नाम के पहचानकर्ताओं के साथ एक और अनुवाद इकाई में संघर्ष नहीं कर सकता है।

bool getState(userType*,otherUserType*); 
} 

और यह वास्तव में एक pessimisation है: getState() बाहरी संबंध है। स्थिर संबंध को प्राथमिकता देना बेहतर होता है, क्योंकि यह प्रतीक तालिका को प्रदूषित नहीं करता है।

static bool getState(/*...*/); 

लिखना बेहतर है। मैं एक ही जाल में गिर गया (मानक में शब्द है जो सुझाव देता है कि फाइल-स्टेटिक्स को किसी भी तरह अज्ञात नेमस्पेस के पक्ष में बहिष्कृत किया गया है), लेकिन केडीई जैसी बड़ी सी ++ परियोजना में काम करना, आपको बहुत से लोग मिलते हैं जो आपके सिर को सही तरीके से बदलते हैं फिर से :)

+7

के बाद से C++ 11 अज्ञात नामस्थान आंतरिक लिंकेज (मानक में खंड 3.5 या http://en.cppreference.com/w/cpp/language/namespace#Unnamed_namespaces) –

+4

है "ये एक गुमनाम में होने की जरूरत नहीं है नाम स्थान "तकनीकी तौर पर, यह सुनिश्चित करें - लेकिन अभी भी, यह उनकी अर्थ विज्ञान का एक दृश्य चेतावनी के रूप में, एक में उन्हें डाल करने के लिए और इसे बनाने के लिए (और भी अधिक) तुच्छ' const'ness दूर करने के लिए बाद में अगर वांछित चोट नहीं करता है। मुझे संदेह है कि इसका मतलब है कि ओपी की टीम कुछ भी समझ में नहीं आती है! साथ ही, अज्ञात नामस्थानों में अज्ञात नेमस्पेस में फ़ंक्शंस के बारे में थोड़ा सा उल्लेख है जैसा कि सी ++ 11 में गलत है। मेरी समझ से, उन्होंने पहले बाहरी लिंकिंग की आवश्यकता वाले टेम्पलेट तर्कों का एक मुद्दा तय किया था, इसलिए आंतरिक लिंकेज रखने के लिए अज्ञात नेमस्पेस (टेम्पलेट तर्क रखने में सक्षम) की अनुमति दे सकती है। –

9

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

उदाहरण के लिए, मेरे सिस्टम पर निम्नलिखित कोड को चलाने का लगभग 70% लगता है यदि अज्ञात नेमस्पेस का उपयोग किया जाता है (x86-64 gcc-4.6.3 और -O2; ध्यान दें कि add_val में अतिरिक्त कोड कंपाइलर बनाता है इसे दो बार शामिल नहीं करना चाहते हैं)।

#include <iostream> 

namespace { 
    double a; 
    void b(double x) 
    { 
    a -= x; 
    } 
    void add_val(double x) 
    { 
    a += x; 
    if(x==0.01) b(0); 
    if(x==0.02) b(0.6); 
    if(x==0.03) b(-0.1); 
    if(x==0.04) b(0.4); 
    } 
} 

int main() 
{ 
    a = 0; 
    for(int i=0; i<1000000000; ++i) 
    { 
     add_val(i*1e-10); 
    } 
    std::cout << a << '\n'; 
    return 0; 
} 
+3

सच होने के लिए बहुत अच्छा - मैंने इस अनुभाग को ओसीसी ऑप्टिमाइज़ेशन का उपयोग करके, जीएससी 4-1-2 पर, नामस्थान कथन के साथ-साथ-बिना: -> एक ही समय (3sec, -O3, और 4sec -O3 के साथ मिला) – Daniel

+0

इस कोड को जानबूझकर संकलक को मनाने के लिए मुख्य में ख और add_val इनलाइन के लिए नहीं की कोशिश करने के जटिल था। O3 ऑप्टिमाइज़ेशन कोड ब्लोट की लागत के बावजूद बहुत सारे इनलाइनिंग का उपयोग करता है। हालांकि, अभी भी ऐसे कार्य हैं जहां ओ 3 add_val इनलाइन नहीं करेगा। आप add_val को अधिक जटिल बनाने की कोशिश कर सकते हैं, या इसे विभिन्न परिस्थितियों में मुख्य से कई बार कॉल कर सकते हैं। – xioxox

+3

@ डैनियल: मुझे क्या याद आ रही है? जैसा कि पढ़ा गया है, आपने कहा है कि आपने '-O3' की तुलना स्वयं की तुलना की है, फिर आपने कहा कि 3 बनाम 4 सेकंड "एक ही समय" हैं। इनमें से कोई भी कुछ समझ में नहीं आता है। मुझे संदेह है कि _real_ स्पष्टीकरण होगा, लेकिन यह क्या है? –

2

अनाम नाम स्थान फ़ाइल, चर, फ़ंक्शन और ऑब्जेक्ट्स को उस फ़ाइल में एक्सेस तक सीमित करता है जिसमें इसे परिभाषित किया गया है। अनामस्थान की कार्यक्षमता सी/सी ++ में static कीवर्ड के समान है।
static कीवर्ड वैश्विक चर के उपयोग को सीमित करता है और उस फ़ाइल में फ़ंक्शन को परिभाषित करता है जिसमें उन्हें परिभाषित किया जाता है।
अनाम नामस्थान और static कीवर्ड के बीच अंतर है क्योंकि अज्ञात नामस्थान का स्थिर मूल्य पर लाभ होता है। static कीवर्ड का उपयोग चर, फ़ंक्शन और ऑब्जेक्ट्स के साथ किया जा सकता है लेकिन उपयोगकर्ता परिभाषित कक्षा के साथ नहीं।
उदाहरण के लिए:

static int x; // Correct 

लेकिन,

static class xyz {/*Body of class*/} //Wrong 
static structure {/*Body of structure*/} //Wrong 

लेकिन इसके साथ ही अज्ञात नाम स्थान के साथ संभव हो सकता है। उदाहरण के लिए,

namespace { 
      class xyz {/*Body of class*/} 
      static structure {/*Body of structure*/} 
    } //Correct 
संबंधित मुद्दे