सदस्य कार्यों में स्थैतिक चर


158

क्या कोई यह बता सकता है कि सदस्य कार्यों में स्थैतिक चर C ++ में कैसे काम करते हैं।

निम्नलिखित वर्ग को देखते हुए:

class A {
   void foo() {
      static int i;
      i++;
   }
}

अगर मैं एक से अधिक उदाहरणों की घोषणा करता हूं A, तो foo()एक उदाहरण पर कॉल करने से स्थैतिक परिवर्तन होता हैi सभी उदाहरणों पर ? या केवल एक ही इसे कहा जाता था?

मैंने मान लिया कि प्रत्येक उदाहरण की अपनी एक प्रति होगी i, लेकिन कुछ कोड के माध्यम से कदम रखना मुझे अन्यथा इंगित करता है।

जवाबों:


169

चूंकि class Aएक गैर-टेम्पलेट वर्ग है और A::foo()एक गैर-टेम्पलेट फ़ंक्शन है। static int iकार्यक्रम के अंदर केवल एक प्रति होगी ।

Aवस्तु का कोई भी उदाहरण उसी को प्रभावित करेगा iऔर जीवनकाल iकार्यक्रम से बाहर रहेगा। एक उदाहरण जोड़ने के लिए:

A o1, o2, o3;
o1.foo(); // i = 1
o2.foo(); // i = 2
o3.foo(); // i = 3
o1.foo(); // i = 4

3
अच्छे उदाहरण के लिए धन्यवाद! क्या वास्तव में कुछ हासिल करने का एक तरीका होगा static int iजो उदाहरण के लिए विशिष्ट का दायरा बनाता है , ताकि उदा o1.foo(); // i = 1और $o2.foo(); // i = 1...?
स्टिंगरी

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

137

staticदुर्भाग्यवश, C ++ में कीवर्ड के कुछ अलग असंबंधित अर्थ हैं

  1. जब डेटा सदस्यों के लिए उपयोग किया जाता है तो इसका मतलब है कि डेटा को कक्षा में आवंटित किया गया है न कि उदाहरणों में।

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

  3. जब एक संकलन इकाई स्तर (मॉड्यूल) पर उपयोग किया जाता है, तो इसका मतलब है कि चर एक वैश्विक की तरह है (यानी आवंटित होने mainसे पहले शुरू और नष्ट कर दिया गया है और mainबाहर निकलने के बाद नष्ट हो जाता है) लेकिन यह कि चर अन्य सुलभ इकाइयों में सुलभ या दृश्यमान नहीं होगा

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

आपके कोड में staticकीवर्ड का उपयोग संख्या 2 के साथ किया जाता है और इसका कक्षाओं या उदाहरणों से कोई लेना-देना नहीं है ... यह फ़ंक्शन का एक चर है और इसकी केवल एक प्रति होगी।

जैसा कि सही रूप से iammilind ने कहा है कि यदि फ़ंक्शन एक टेम्प्लेट फ़ंक्शन था, तो उस वेरिएबल के कई उदाहरण हो सकते हैं (क्योंकि उस स्थिति में वास्तव में फ़ंक्शन प्रोग्राम में कई अलग-अलग प्रतियों में मौजूद हो सकता है)। यहां तक ​​कि पाठ्यक्रम के वर्गों और उदाहरणों के मामले में अप्रासंगिक हैं ... निम्नलिखित उदाहरण देखें:

#include <stdio.h>

template<int num>
void bar()
{
    static int baz;
    printf("bar<%i>::baz = %i\n", num, baz++);
}

int main()
{
    bar<1>(); // Output will be 0
    bar<2>(); // Output will be 0
    bar<3>(); // Output will be 0
    bar<1>(); // Output will be 1
    bar<2>(); // Output will be 1
    bar<3>(); // Output will be 1
    bar<1>(); // Output will be 2
    bar<2>(); // Output will be 2
    bar<3>(); // Output will be 2
    return 0;
}

41
+1 के लिए keyword static unfortunately has a few different unrelated meanings in C++:)
iammilind

दुनिया इसे पढ़ने के बाद बहुत अधिक समझ में आता है, धन्यवाद
एरिन

मुझे टेम्पलेट के साथ चाल पसंद है। मैं इसका उपयोग करने का बहाना खोजने के लिए इंतजार नहीं कर सकता।
टॉम ज़ातो -

किसी को "अनाम नामस्थान के पक्ष में कुछ हतोत्साहित" के लिए एक संदर्भ मिला?
ऑस्टिनमार्टन

3
@austinmarton: "स्थानीय से अनुवाद इकाई 'को इंगित करने के लिए" स्टेटिक टू ट्रांसलेशन यूनिट "वाक्यांश का उपयोग C ++ में किया गया है। इसके बजाय अनाम नामस्थान का उपयोग करें (8.2.5.1)" मेरे संस्करण में C ++ प्रोग्रामिंग लैंग्वेज (10 सितंबर, सितंबर 1999) पर मौजूद है। पृष्ठ 819 पर
6502

2

कार्यों के अंदर स्थैतिक चर

  • स्टैटिक वैरिएबल एक फंक्शन के अंदर बनाया जाता है, प्रोग्राम के स्टैटिक मेमोरी में स्टैक पर नहीं।

  • फ़ंक्शन के पहले कॉल पर स्टेटिक वैरिएबल इनिशियलाइज़ेशन किया जाएगा।

  • स्टेटिक वैरिएबल कई फ़ंक्शन कॉल में मान को बनाए रखेगा

  • स्टेटिक वैरिएबल का लाइफटाइम प्रोग्राम है

यहां छवि विवरण दर्ज करें

उदाहरण

#include <iostream>

using namespace std;

class CVariableTesting 
{
    public:
    
    void FuncWithStaticVariable();
    void FuncWithAutoVariable();

};

void CVariableTesting::FuncWithStaticVariable()
{
    static int staticVar = 0; //staticVar is initialised by 0 the first time
    cout<<"Variable Value : "<<staticVar<<endl;
    staticVar++;
}
void CVariableTesting::FuncWithAutoVariable()
{
    int autoVar = 0;
    cout<<"Variable Value : "<<autoVar<<endl;
    autoVar++;
}
    

int main()
{
    CVariableTesting objCVariableTesting;
    cout<<"Static Variable";
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    
    cout<<endl;
    cout<<"Auto Variable";
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    
    return 0;
}

आउटपुट:

स्थैतिक चर

परिवर्तनीय मूल्य: ०
परिवर्तनीय मूल्य: १
परिवर्तनीय मूल्य: २
परिवर्तनीय मूल्य: ३
परिवर्तनीय मूल्य: ४

ऑटो चर

परिवर्तनीय मूल्य: ०
परिवर्तनीय मूल्य: ०
परिवर्तनीय मूल्य: ०
परिवर्तनीय मूल्य: ०
परिवर्तनीय मूल्य: ०


-2

सरलीकृत उत्तर:

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


9
ग्लोबल्स की शुरुआत प्रोग्राम स्टार्टअप में की जाती है, फंक्शन स्टेटिक्स को पहले उपयोग में लिया जाता है। यह एक बड़ा अंतर है।
6502

मुझे नहीं लगता कि ऐसा होता है। हालांकि, यह किसी भी तरह संकलक होना चाहिए।
0xbadf00d

2
फिर आप गलत सोचते हैं: C ++ मानक में 3.6.1 यह तय करता है कि स्टार्टअप पर स्थिर भंडारण अवधि के साथ नेमस्पेस स्कोप के ऑब्जेक्ट का निर्माण स्टार्टअप पर होता है; 6.7 (4) तय करता है कि सामान्य रूप से "... इस तरह के एक वैरिएबल को आरंभीकृत किया जाता है, पहली बार नियंत्रण इसकी घोषणा के माध्यम से गुजरता है; इस तरह के एक वैरिएबल को इसके आरंभीकरण के पूरा होने पर आरंभिक माना जाता है"। वैसे यह प्रारंभिक-ऑन-प्रथम-उपयोग आलसी सिंगलटन निर्माण को लागू करने के लिए बहुत आसान है।
6502

3.7.4: "स्थैतिक भंडारण अवधि के साथ ब्लॉक-स्कोप इकाई की निरंतर आरंभीकरण (3.6.2), यदि लागू हो, तो इसके ब्लॉक को पहले दर्ज करने से पहले किया जाता है। कार्यान्वयन को अन्य ब्लॉक-स्कोप वैरिएबल्स के शुरुआती आरंभीकरण की अनुमति है। स्थैतिक या थ्रेड स्टोरेज की अवधि एक ही शर्तों के तहत जिसे कार्यान्वयन को वैचारिक रूप से वैरिएबल को थ्रेड या थ्रेड स्टोरेज अवधि के साथ नामस्थान स्कोप (3.6.2) में शुरू करने की अनुमति है। अन्यथा इस तरह के एक वैरिएबल को इनिशियलाइज़ किया जाता है जब पहली बार नियंत्रण इसकी घोषणा से गुजरता है; "
0xbadf00d

1
हालांकि पर्याप्त रूप से पर्याप्त: 1) निरंतर इनिशियलाइज़ेशन के लिए, यह चर्चा करना अप्रासंगिक है कि क्या किसी स्थानीय स्थैतिक को पहली बार ब्लॉक में प्रवेश करने से पहले इनिशियलाइज़ किया जा सकता है (वेरिएबल केवल ब्लॉक के अंदर दिखाई देता है और लगातार इनिशियलाइज़ेशन कोई साइड इफेक्ट पैदा नहीं करता है); 2) आपकी पोस्ट में कुछ भी निरंतर आरंभीकरण के बारे में नहीं कहा गया है; 3) स्थानीय स्टेटिक्स गैर-स्थिरीकरण के लिए बहुत उपयोगी होते हैं जैसे MyClass& instance(){ static MyClass x("config.ini"); return x; }- सिंगल-थ्रेड उपयोग के लिए एक वैध पोर्टेबल कार्यान्वयन बिल्कुल क्योंकि स्थानीय स्टेटिक्स आपके कहने के बावजूद एक वैश्विक की तरह नहीं हैं।
६५०२
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.