अनाम नाम स्थान का उपयोग क्यों किया जाता है और उनके लाभ क्या हैं?


242

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

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

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

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

जवाबों:


189

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

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

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

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

namespace { int a1; }
static int a2;

दोनों aअनुवाद इकाई स्थानीय हैं और लिंक समय पर क्लैश नहीं करेंगे। लेकिन अंतर यह है कि a1अनाम नामस्थान में एक अद्वितीय नाम मिलता है।

कॉमे-कंप्यूटिंग में उत्कृष्ट लेख पढ़ें स्थैतिक के बजाय एक अनाम नाम स्थान का उपयोग क्यों किया जाता है? ( Archive.org मिरर )।


आप संबंध को समझाते हैं static। क्या आप कृपया तुलना भी कर सकते हैं __attribute__ ((visibility ("hidden")))?
फ़िनज़

74

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

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

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

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;

14

फाइल के लिए क्लास, वैरिएबल, फंक्शन और ऑब्जेक्ट्स में हैडस्पेस की पहुंच सीमित है। नाम स्थान की कार्यक्षमता staticC / C ++ में कीवर्ड के समान है ।
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

13

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

उदाहरण के लिए, मेरे सिस्टम पर निम्न कोड रन समय का लगभग 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;
}

5
सच होने के लिए बहुत अच्छा है - मैंने इस खंड को 4-1-2 पर आज़माया, O3 अनुकूलन का उपयोग करते हुए, बिना नाम-विवरण के कथन के साथ: -> एक ही समय मिला (3sec, साथ -O3, और 4sec with -O3)
थियो

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

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

@underscore_d उत्तर स्थिति -O2 का उपयोग दोनों मामलों में किया गया था, -O3 में नहीं। अलग-अलग अनुकूलन स्तर अलग-अलग व्यवहार कर सकते हैं। इसके अलावा, अलग-अलग संकलक संस्करण अलग-अलग व्यवहार कर सकते हैं (उत्तर पुराना हो सकता है, वह है)
पॉल स्टेलियन

1
@PaStStelian मुझे पता है कि, लेकिन यह बहुत स्पष्ट प्रतीत होता है कि मैं जियॉक्सॉक्स के उत्तर का जवाब नहीं दे रहा था, बल्कि थियो की टिप्पणी के अनुसार (या तो उसका नाम बदल दिया गया है या मैं किसी तरह मिल गया हूं)
अंडरस्कोर

12

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

namespace {
    const int SIZE_OF_ARRAY_X;
    const int SIZE_OF_ARRAY_Y;

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

    bool getState(userType*,otherUserType*);
}

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

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

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


10
चूंकि c ++ 11 अनाम नामस्थान में आंतरिक लिंकेज है (मानक में 3.5 खंड या en.cppreference.com/w/cpp/language/namespace#Unonym_namespaces )
एमिल विराजदास

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

11

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

"क्या मैं चाहता हूं कि यह चर, कार्य, वर्ग, आदि सार्वजनिक या निजी हो?"


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

2
तुम्हारी बात तथ्य पूर्ण है; कम से कम जहाँ तक आज C ++ है। हालाँकि, C ++ 98 / C ++ 03 आवश्यक चीज़ों में बाहरी लिंकेज है ताकि टेम्पलेट तर्कों के रूप में उपयोग किया जा सके। चूंकि अनाम नेमस्पेस में चीजें टेम्पलेट तर्कों के रूप में उपलब्ध हैं, इसलिए उनके पास बाहरी लिंकेज होगा (कम से कम प्री-सी ++ 11 में) यहां तक ​​कि अगर फ़ाइल के बाहर से उन्हें संदर्भित करने का कोई तरीका नहीं था। मुझे लगता है कि उस पर दबाव डालने की कुछ क्षमता हो सकती है, क्योंकि मानक को केवल उन चीजों की आवश्यकता होती है जैसे नियम लागू किए गए थे; और कभी-कभी ऐसा करना संभव है कि वास्तव में नियमों को लागू किए बिना।
मैक्स लाइब्बर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.