विषय पर बढ़ें

अंतिम अद्यतन:2026-10-13

C++ static: स्टैटिक वेरिएबल और मेंबर

लेखक के बारे में

WeChat सार्वजनिक अकाउंट:

C++ static विस्तार से: स्टैटिक वेरिएबल, मेंबर और फ़ंक्शन | C++那些事

विभिन्न प्रकार की चीज़ों के साथ प्रयोग करने पर static कीवर्ड के अलग-अलग अर्थ होते हैं। हम static कीवर्ड का उपयोग इस प्रकार कर सकते हैं:

स्टैटिक वेरिएबल: फ़ंक्शन में वेरिएबल, क्लास में वेरिएबल

क्लास के स्टैटिक मेंबर: क्लास ऑब्जेक्ट और क्लास में फ़ंक्शन

अब आइए static के इन उपयोगों को विस्तार से देखें:

स्टैटिक वेरिएबल

  • फ़ंक्शन में स्टैटिक वेरिएबल

जब कोई वेरिएबल static घोषित किया जाता है, तो उसके लिए स्पेस प्रोग्राम के पूरे जीवनकाल के लिए आवंटित होती है। भले ही फ़ंक्शन कितनी ही बार कॉल हो, स्टैटिक वेरिएबल की स्पेस केवल एक बार आवंटित होती है, और पिछली कॉल का वेरिएबल मान अगली फ़ंक्शन कॉल तक चला जाता है। यह C / C++ या ऐसे किसी भी अन्य एप्लिकेशन में बहुत उपयोगी है जिसमें फ़ंक्शन की पिछली स्थिति को संग्रहीत करने की आवश्यकता होती है।

#include <iostream> 
#include <string> 
using namespace std; 

void demo() 
{ 
    // static variable 
    static int count = 0; 
    cout << count << " "; 

    // value is updated and 
    // will be carried to next 
    // function calls 
    count++; 
} 

int main() 
{ 
    for (int i=0; i<5; i++)  
        demo(); 
    return 0; 
} 

आउटपुट:

0 1 2 3 4 

आप उपरोक्त प्रोग्राम में देख सकते हैं कि वेरिएबल count को static घोषित किया गया है। इसलिए इसका मान फ़ंक्शन कॉलों के बीच चला जाता है। फ़ंक्शन जितनी बार भी कॉल हो, वेरिएबल count को दोबारा इनिशियलाइज़ नहीं किया जाता।

  • क्लास में स्टैटिक वेरिएबल

चूँकि static घोषित वेरिएबल केवल एक बार इनिशियलाइज़ होते हैं — क्योंकि उनके लिए अलग स्टैटिक स्टोरेज में स्पेस आवंटित होती है — इसलिए क्लास में स्टैटिक वेरिएबल ऑब्जेक्ट्स द्वारा साझा किए जाते हैं। विभिन्न ऑब्जेक्ट्स के लिए एक ही स्टैटिक वेरिएबल की कई प्रतियाँ नहीं हो सकतीं। इसी कारण से स्टैटिक वेरिएबल को कंस्ट्रक्टर का उपयोग करके इनिशियलाइज़ नहीं किया जा सकता।

#include<iostream> 
using namespace std; 

class Apple 
{ 
public: 
    static int i; 

    Apple() 
    { 
        // Do nothing 
    }; 
}; 

int main() 
{ 
Apple obj1; 
Apple obj2; 
obj1.i =2; 
obj2.i = 3; 

// prints value of i 
cout << obj1.i<<" "<<obj2.i; 
} 

आप उपरोक्त प्रोग्राम में देख सकते हैं कि हमने कई ऑब्जेक्ट्स के लिए स्टैटिक वेरिएबल i की कई प्रतियाँ बनाने का प्रयास किया। लेकिन ऐसा नहीं हुआ। इसलिए क्लास में स्टैटिक वेरिएबल को उपयोगकर्ता द्वारा क्लास के बाहर, क्लास के नाम और स्कोप रेज़ोल्यूशन ऑपरेटर का उपयोग करके, नीचे दिखाए अनुसार स्पष्ट रूप से इनिशियलाइज़ किया जाना चाहिए:

#include<iostream> 
using namespace std; 

class Apple 
{ 
public: 
    static int i; 

    Apple() 
    { 
        // Do nothing 
    }; 
}; 

int Apple::i = 1; 

int main() 
{ 
    Apple obj; 
    // prints value of i 
    cout << obj.i; 
} 

आउटपुट:

1

स्टैटिक मेंबर

  • क्लास ऑब्जेक्ट को static बनाना

वेरिएबल की तरह ही, static घोषित किए गए ऑब्जेक्ट का स्कोप भी प्रोग्राम के जीवनकाल के अंत तक रहता है।

निम्नलिखित प्रोग्राम पर विचार करें, जिसमें ऑब्जेक्ट नॉन-स्टैटिक है।

#include<iostream> 
using namespace std; 

class Apple 
{ 
    int i; 
    public: 
        Apple() 
        { 
            i = 0; 
            cout << "Inside Constructor\n"; 
        } 
        ~Apple() 
        { 
            cout << "Inside Destructor\n"; 
        } 
}; 

int main() 
{ 
    int x = 0; 
    if (x==0) 
    { 
        Apple obj; 
    } 
    cout << "End of main\n"; 
} 

आउटपुट:

Inside Constructor
Inside Destructor
End of main

उपरोक्त प्रोग्राम में, ऑब्जेक्ट को if ब्लॉक के भीतर नॉन-स्टैटिक घोषित किया गया है। इसलिए वेरिएबल का स्कोप केवल if ब्लॉक के भीतर ही है। इस प्रकार, ऑब्जेक्ट बनने पर कंस्ट्रक्टर कॉल होता है, और if ब्लॉक का नियंत्रण उससे आगे निकलते ही डिस्ट्रक्टर कॉल हो जाता है, क्योंकि ऑब्जेक्ट का स्कोप उस if ब्लॉक तक सीमित है जिसमें उसे घोषित किया गया है।

यदि हम ऑब्जेक्ट को static घोषित करें, तो आइए देखें कि आउटपुट कैसे बदलता है।

#include<iostream> 
using namespace std; 

class Apple 
{ 
    int i; 
    public: 
        Apple() 
        { 
            i = 0; 
            cout << "Inside Constructor\n"; 
        } 
        ~Apple() 
        { 
            cout << "Inside Destructor\n"; 
        } 
}; 

int main() 
{ 
    int x = 0; 
    if (x==0) 
    { 
        static Apple obj; 
    } 
    cout << "End of main\n"; 
} 

आउटपुट:

Inside Constructor
End of main
Inside Destructor

आप आउटपुट में बदलाव स्पष्ट रूप से देख सकते हैं। अब डिस्ट्रक्टर main के समाप्त होने के बाद कॉल होता है। ऐसा इसलिए है क्योंकि स्टैटिक ऑब्जेक्ट का स्कोप प्रोग्राम के पूरे जीवनकाल तक फैला होता है।

  • क्लास में स्टैटिक फ़ंक्शन

क्लास में स्टैटिक डेटा मेंबर या स्टैटिक वेरिएबल की तरह ही, स्टैटिक मेंबर फ़ंक्शन भी क्लास के ऑब्जेक्ट पर निर्भर नहीं होते। हमें ऑब्जेक्ट और '.' का उपयोग करके स्टैटिक मेंबर फ़ंक्शन को कॉल करने की अनुमति है। लेकिन स्टैटिक मेंबर को क्लास के नाम और स्कोप रेज़ोल्यूशन ऑपरेटर से कॉल करने की सिफ़ारिश की जाती है।

स्टैटिक मेंबर फ़ंक्शन को केवल स्टैटिक डेटा मेंबर या अन्य स्टैटिक मेंबर फ़ंक्शन तक पहुँचने की अनुमति है; वे क्लास के नॉन-स्टैटिक डेटा मेंबर या मेंबर फ़ंक्शन तक नहीं पहुँच सकते।

#include<iostream> 
using namespace std; 

class Apple 
{ 
    public: 
        // static member function 
        static void printMsg() 
        {
            cout<<"Welcome to Apple!"; 
        }
}; 

// main function 
int main() 
{ 
    // invoking a static member function 
    Apple::printMsg(); 
} 

आउटपुट:

Welcome to Apple!

पहुँच की सीमा को सीमित करना

static का एक काम पहुँच की सीमा को सीमित करना भी है (अनाम नेमस्पेस के समान)। issue से: https://github.com/Light-City/CPlusPlusThings/issues/142

// source1.cpp
extern void sayHello();
const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}

// source2.cpp
#include <cstdio>
extern char* msg;
void sayHello()
{
    printf("%s", msg);
}

g++ उपरोक्त दो कोड फ़ाइलों को सामान्य रूप से कंपाइल करके Hello World! प्रिंट कर सकता है, लेकिन यदि आप source1.cpp में msg पर static लगा दें, तो 'undefined reference to msg' की कंपाइल त्रुटि उत्पन्न होगी:

// source1.cpp
extern void sayHello();
static const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}

static का आंतरिक लिंकेज (पहुँच की सीमा को सीमित करना)

issue #142 के संकेत के लिए धन्यवाद: जब static किसी ग्लोबल वेरिएबल/फ़ंक्शन को क्वालिफ़ाई करता है, तो वह पहुँच की सीमा को सीमित करने का काम भी करता है — यह उसके लिंकेज को बाहरी लिंकेज से आंतरिक लिंकेज में बदल देता है, जिसका प्रभाव अनाम नेमस्पेस जैसा है:

  • static रहित ग्लोबल वेरिएबल: अन्य ट्रांसलेशन यूनिट extern घोषणा के माध्यम से उस तक पहुँच सकती हैं;
  • static ग्लोबल वेरिएबल/फ़ंक्शन: केवल वर्तमान ट्रांसलेशन यूनिट में दिखाई देता है; extern घोषणा से भी उससे लिंक नहीं हो सकता (undefined reference)।

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

// file1.cpp
static int hidden = 42;          // 内部链接:其他文件 extern 不可见
int visible = 1;                 // 外部链接:其他文件可 extern 访问

namespace {                      // 匿名命名空间:等价且更现代的写法
    int also_hidden = 7;
}

सामान्य प्रश्न

static ग्लोबल और सामान्य ग्लोबल में क्या अंतर है?

static ग्लोबल की लिंकेज आंतरिक होती है: केवल अपनी ट्रांसलेशन यूनिट में दिखता है। सामान्य ग्लोबल फ़ाइलों के पार दिखता है और सिंबल टकराव का कारण बनता है।

static लोकल वेरिएबल कब इनिशियलाइज़ होता है?

परिभाषा पर पहली बार पहुँचने पर एक बार; C++11 से यह थ्रेड-सेफ है और आयु प्रोग्राम के अंत तक।

क्या स्टैटिक मेंबर फ़ंक्शन गैर-स्टैटिक मेंबर एक्सेस कर सकता है?

नहीं। इसमें this पॉइंटर नहीं होता, केवल स्टैटिक मेंबर ही एक्सेस कर सकता है।

संबंधित विषय

टिप्पणियाँ