C और C ++ में 'स्थैतिक स्थैतिक' का क्या अर्थ है?


117
const static int foo = 42;

मैंने इसे StackOverflow पर कुछ कोड में देखा और मैं यह पता नहीं लगा सका कि यह क्या करता है। फिर मैंने अन्य मंचों पर कुछ भ्रमित जवाब देखे। मेरा सबसे अच्छा अनुमान है कि इसका उपयोग C में fooअन्य मॉड्यूल से निरंतर छिपाने के लिए किया जाता है । क्या ये सही है? यदि हां, तो कोई इसे C ++ संदर्भ में क्यों उपयोग करेगा जहां आप इसे बना सकते हैं private?

जवाबों:


113

इसका C और C ++ दोनों में उपयोग है।

जैसा कि आपने अनुमान लगाया है, staticभाग उस संकलन इकाई तक अपना दायरा सीमित करता है । यह स्थैतिक आरंभ के लिए भी प्रदान करता है। constकंपाइलर को बताता है कि किसी को भी इसे संशोधित नहीं करने दें। यह चर या तो डेटा या bss सेगमेंट में आर्किटेक्चर के आधार पर डाला जाता है, और स्मृति में केवल पढ़ने के लिए चिह्नित किया जा सकता है।

सब है कि कैसे सी इन चर व्यवहार करता है (या कैसे सी ++ नामस्थान चर व्यवहार करता है)। C ++ में, एक चिन्हित सदस्य staticको दिए गए वर्ग के सभी उदाहरणों द्वारा साझा किया जाता है। यह निजी है या नहीं इस तथ्य को प्रभावित नहीं करता है कि एक चर कई उदाहरणों द्वारा साझा किया जाता है। बीत रहा है constवहाँ पर आपको चेतावनी देता है किसी भी कोड को संशोधित करने की कोशिश करेगा होगा।

यदि यह सख्ती से निजी था, तो कक्षा के प्रत्येक उदाहरण को अपना स्वयं का संस्करण (आशावादी होने के बावजूद) मिलेगा।


1
मूल उदाहरण एक "निजी चर" के बारे में बात कर रहा है। इसलिए, यह एक mebmer है और स्थैतिक लिंकेज पर कोई प्रभाव नहीं है । आपको "उस फ़ाइल का स्कोप वाला स्टैटिक पार्ट लिमिट" हटा देना चाहिए।
रिचर्ड कॉर्डन

"विशेष खंड" को डेटा खंड के रूप में जाना जाता है, जिसे वह अन्य सभी वैश्विक चर जैसे स्पष्ट "तार" और वैश्विक सरणियों के साथ साझा करता है। यह कोड सेगमेंट का विरोध कर रहा है।
स्पूलसन 10

@ रिचर्ड - क्या आपको लगता है कि यह एक वर्ग का सदस्य है? सवाल में ऐसा कुछ भी नहीं है जो यह कहता है। यदि यह किसी वर्ग का सदस्य है, तो आप सही हैं, लेकिन अगर यह वैश्विक दायरे में घोषित किया गया एक चर है, तो क्रिस सही है।
ग्रीम पेरो

1
मूल पोस्टर ने निजी का संभावित बेहतर समाधान के रूप में उल्लेख किया, लेकिन मूल समस्या के रूप में नहीं।
बजे क्रिस आर्गुइन

@Gememe, ठीक है तो यह निश्चित रूप से "सदस्य" नहीं है - हालांकि, यह उत्तर बयान कर रहा है जो केवल नाम स्थान के सदस्यों पर लागू होता है और वे कथन सदस्य चर के लिए गलत हैं। वोटों की मात्रा को देखते हुए त्रुटि किसी को भ्रमित कर सकती है जो भाषा से बहुत परिचित नहीं है - इसे ठीक किया जाना चाहिए।
रिचर्ड कॉर्डन

212

बहुत से लोगों ने मूल जवाब दिया लेकिन किसी ने भी नहीं बताया कि सी ++ में स्तर पर constचूक हुई (और कुछ ने गलत जानकारी दी)। C ++ 98 मानक अनुभाग 3.5.3 देखें।staticnamespace

पहले कुछ पृष्ठभूमि:

अनुवाद इकाई: प्री-प्रोसेसर के बाद एक स्रोत फ़ाइल (पुनरावर्ती) में इसकी सभी शामिल फाइलें शामिल हैं।

स्टेटिक लिंकेज: एक प्रतीक केवल इसकी अनुवाद इकाई के भीतर उपलब्ध है।

बाहरी लिंकेज: एक प्रतीक अन्य अनुवाद इकाइयों से उपलब्ध है।

पर namespaceस्तर

इसमें वैश्विक नामस्थान उर्फ ​​वैश्विक चर शामिल हैं

static const int sci = 0; // sci is explicitly static
const int ci = 1;         // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3;        // ei is explicitly extern
int i = 4;                // i is implicitly extern
static int si = 5;        // si is explicitly static

समारोह स्तर पर

staticफ़ंक्शन कॉल के बीच मान बनाए रखा जाता है।
फंक्शन staticवेरिएबल्स का शब्दार्थ वैश्विक वेरिएबल्स के समान है जिसमें वे प्रोग्राम के डेटा-सेगमेंट (और स्टैक या हीप) में रहते हैं, इस सवाल को staticवेरिएबल के जीवनकाल के बारे में अधिक जानकारी के लिए देखें ।

पर classस्तर

staticका मतलब है कि मूल्य वर्ग के सभी उदाहरणों के बीच साझा किया जाता है और constइसका मतलब है कि यह नहीं बदलता है।


2
समारोह के स्तर पर: स्थैतिक कांस्टेबल के साथ अतिरेक नहीं होता है, वे अलग-अलग व्यवहार कर सकते हैं const int *foo(int x) {const int b=x;return &b};बनामconst int *foo(int x) {static const int b=x;return &b};
हनकार

1
प्रश्न C और C ++ दोनों के बारे में है, इसलिए आपको उत्तरार्द्ध में constकेवल आसन के बारे में एक नोट शामिल करना चाहिए static
निकोलाई रुहे

@ मोती: शानदार जवाब। क्या आप बता सकते हैं कि फ़ंक्शन स्तर पर क्या बेमानी है? क्या आप कह रहे हैं कि constघोषणा का मतलब staticवहाँ भी है? जैसे, यदि आप constदूर जाते हैं, और मूल्य को संशोधित करते हैं, तो सभी मान संशोधित किए जाएंगे?
कुकी

1
@Moti constफंक्शन लेवल पर स्टैटिकली नहीं होता है, जो कि कंफर्टेबल नाइटमेयर (कॉन्स्टेंट ! = कॉन्स्टेंट एक्सप्रेशन) होगा, फंक्शन लेवल की हर चीज इनफैक्टली होती है auto। चूँकि इस प्रश्न को टैग किया गया है [c] साथ ही, मुझे यह उल्लेख करना चाहिए कि वैश्विक स्तर const intपर externC. में निहित है। आपके द्वारा यहाँ दिए गए नियम C ++ का पूरी तरह से वर्णन करते हैं।
रियान हेनिंग

1
और सी ++ में, तीनों मामलों में, staticइंगित करता है कि चर स्थिर अवधि है (केवल एक प्रति मौजूद है, जो कार्यक्रम की शुरुआत से उसके अंत तक रहता है), और आंतरिक / स्थैतिक संबंध है यदि अन्यथा निर्दिष्ट नहीं है (यह फ़ंक्शन के ओवरराइड है स्थानीय स्थैतिक चर के लिए लिंकेज, या स्थिर सदस्यों के लिए क्लास 'लिंकेज)। मुख्य अंतर यह है कि प्रत्येक स्थिति में इसका क्या अर्थ है जहां staticमान्य है।
जस्टिन टाइम -

45

कोड की वह रेखा वास्तव में कई अलग-अलग संदर्भों में दिखाई दे सकती है और इसके अलावा यह लगभग समान व्यवहार करती है, छोटे अंतर हैं।

नेमस्पेस स्कोप

// foo.h
static const int i = 0;

' i' हर अनुवाद इकाई में दिखाई देगा जिसमें हेडर शामिल है। हालांकि, जब तक आप वास्तव में ऑब्जेक्ट के पते का उपयोग नहीं करते हैं (उदाहरण के लिए। ' &i'), मुझे पूरा यकीन है कि कंपाइलर ' i' को बस एक प्रकार की सुरक्षा के रूप में मानेगा 0। जहाँ दो और अनुवाद इकाइयाँ ' &i' लेती हैं, तो पता प्रत्येक अनुवाद इकाई के लिए अलग होगा।

// foo.cc
static const int i = 0;

' i' में आंतरिक लिंकेज है, और इसलिए इस अनुवाद इकाई के बाहर से संदर्भित नहीं किया जा सकता है। हालाँकि, फिर से जब तक आप इसके पते का उपयोग नहीं करेंगे, तब तक यह सबसे अधिक सुरक्षित प्रकार का माना जाएगा 0

एक बात जो इंगित करने लायक है, वह यह है कि निम्नलिखित घोषणा:

const int i1 = 0;

है वास्तव में के रूप में ही static const int i = 0। एक नेमस्पेस में परिवर्तनशील constऔर स्पष्ट रूप से घोषित नहीं किया गया externहै। यदि आप इस बारे में सोचते हैं, तो यह C ++ समिति का उद्देश्य था कि ODR को तोड़ने से बचने के constलिए staticकीवर्ड की आवश्यकता के बिना हेडर फ़ाइलों में वेरिएबल्स को घोषित करने की अनुमति दी जाए ।

क्लास स्कोप

class A {
public:
  static const int i = 0;
};

उपरोक्त उदाहरण में, मानक स्पष्ट रूप से निर्दिष्ट करता है कि ' i' को परिभाषित करने की आवश्यकता नहीं है यदि उसका पता आवश्यक नहीं है। दूसरे शब्दों में यदि आप केवल ' i' को टाइप-सेफ 0 के रूप में उपयोग करते हैं तो कंपाइलर इसे परिभाषित नहीं करेगा। वर्ग और नामस्थान संस्करणों के बीच एक अंतर यह है कि ' i' (यदि दो अयस्क अधिक अनुवाद इकाइयों में उपयोग किया जाता है) का पता कक्षा के सदस्य के लिए समान होगा। जहां पते का उपयोग किया जाता है, आपके पास इसके लिए एक परिभाषा होनी चाहिए:

// a.h
class A {
public:
  static const int i = 0;
};

// a.cc
#include "a.h"
const int A::i;            // Definition so that we can take the address

2
+1 इंगित करने के लिए कि स्थैतिक कास्ट केवल नेमस्पेस स्कोप में कास्ट के समान है।
प्लमरेटर

वास्तव में "foo.h" या "foo.cc" में रखने के बीच कोई अंतर नहीं है। इसका अनुवाद अनुवाद इकाई को संकलित करते समय .h को शामिल किया जाता है।
मिखाइल

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

24

यह एक छोटा सा स्थान अनुकूलन है।

जब आप कहें

const int foo = 42;

आप एक स्थिरांक को परिभाषित नहीं कर रहे हैं, बल्कि केवल-पढ़ने योग्य चर बना रहे हैं। कंपाइलर 42 का उपयोग करने के लिए पर्याप्त स्मार्ट है जब भी यह फू को देखता है, लेकिन यह इसके लिए आरंभीकृत डेटा क्षेत्र में स्थान भी आवंटित करेगा। ऐसा इसलिए किया जाता है, क्योंकि जैसा कि परिभाषित किया गया है, फू में बाहरी संबंध है। एक और संकलन इकाई कह सकती है:

extern const int फू;

इसके मूल्य तक पहुंच प्राप्त करने के लिए। यह अच्छा अभ्यास नहीं है क्योंकि उस संकलन इकाई को पता नहीं है कि फू का मूल्य क्या है। यह सिर्फ जानता है कि यह एक कास्ट इंट है और जब भी इसका उपयोग किया जाता है, तो इसे मेमोरी से मान को फिर से लोड करना पड़ता है।

अब, यह घोषित करके कि यह स्थिर है:

static const int foo = 42;

संकलक अपना सामान्य अनुकूलन कर सकता है, लेकिन यह भी कह सकता है "हे, इस संकलन इकाई के बाहर कोई भी फू को नहीं देख सकता है और मुझे पता है कि यह हमेशा 42 है इसलिए इसके लिए कोई स्थान आवंटित करने की आवश्यकता नहीं है।"

मुझे यह भी ध्यान रखना चाहिए कि C ++ में, मौजूदा संकलन इकाई से बचने के लिए नामों को रोकने का पसंदीदा तरीका अनाम नाम स्थान का उपयोग करना है:

namespace {
    const int foo = 42; // same as static definition above
}

1
, स्टैटिक का उपयोग किए बिना उल्लिखित "यह इसके लिए आरम्भिक डेटा क्षेत्र में स्थान भी आवंटित करेगा"। और स्थैतिक का उपयोग करके "इसके लिए कोई स्थान आवंटित करने की आवश्यकता नहीं है"। (जहां से संकलक घाटी को उठा रहा है?) क्या आप ढेर के ढेर और ढेर की व्याख्या कर सकते हैं जहां चर संग्रहीत किया जा रहा है। मुझे बताएं कि क्या मैं व्याख्या कर रहा हूं। गलत ।
निहार

@ एन.निहार - स्टैटिक डेटा एरिया मेमोरी का एक निश्चित आकार का हिस्सा है जिसमें सभी डेटा होते हैं जिसमें स्टैटिक लिंकेज होता है। यह प्रोग्राम को मेमोरी में लोड करने की प्रक्रिया द्वारा "आवंटित" किया गया है। यह ढेर या ढेर का हिस्सा नहीं है।
फेर्रुकियो

यदि मेरे पास कोई फ़ंक्शन है तो कोई सूचक को फू करने के लिए लौटाता है? क्या इससे अनुकूलन टूटता है?
एन.वी.

@ nw: हाँ, यह करना होगा।
फेरुशियो

8

यह एक 'int' याद आ रही है। यह होना चाहिए:

const static int foo = 42;

C और C ++ में, यह मान 42 के स्थानीय फ़ाइल दायरे के साथ पूर्णांक स्थिरांक की घोषणा करता है।

42 क्यों? यदि आप पहले से नहीं जानते हैं (और यह विश्वास करना मुश्किल है कि आप नहीं हैं), यह उत्तर जीवन, ब्रह्मांड और सब कुछ के लिए एक संदर्भ है


धन्यवाद ... अब हर बार ... मेरे जीवन के बाकी हिस्सों के लिए ... जब मैं 42 साल का होता हूं, तो मैं हमेशा इस बारे में बात करूंगा। haha
Inisheer

यह प्रमाण-सकारात्मक है कि ब्रह्मांड 13 उंगलियों (प्रश्न और उत्तर वास्तव में आधार 13 में मेल खाता है) के साथ बनाया गया था।
paxdiablo

इसके चूहे। प्रत्येक पैर पर 3 पैर, प्लस एक पूंछ आपको आधार 13.
कीथब

आपको वास्तव में एक घोषणा में 'int' की आवश्यकता नहीं है, हालांकि इसे लिखने के लिए निश्चित रूप से अच्छा स्वाद है। C हमेशा डिफ़ॉल्ट रूप से 'int' प्रकार मानता है। कोशिश करो!
ephemient

"मान 42 की स्थानीय फ़ाइल गुंजाइश के साथ" ?? या यह पूरे संकलन इकाई के लिए है?
aniliitb10

4

C ++ में,

static const int foo = 42;

स्थिरांक को परिभाषित करने और उपयोग करने का पसंदीदा तरीका है। यानी इसके बजाय इसका उपयोग करें

#define foo 42

क्योंकि यह टाइप-सेफ्टी सिस्टम को नहीं हटाता है।


4

सभी महान उत्तरों के लिए, मैं एक छोटा सा विवरण जोड़ना चाहता हूं:

यदि आप प्लगइन्स लिखते हैं (जैसे DLL या .so पुस्तकालयों को एक सीएडी सिस्टम द्वारा लोड किया जाना है), तो स्टेटिक एक जीवन रक्षक है जो इस तरह के नाम टकराव से बचा जाता है:

  1. CAD सिस्टम एक प्लगइन A को लोड करता है, जिसमें "const int foo = 42;" इस में।
  2. सिस्टम एक प्लगइन B को लोड करता है, जिसमें "const int foo = 23;" इस में।
  3. नतीजतन, प्लगइन बी फू के लिए मूल्य 42 का उपयोग करेगा, क्योंकि प्लगइन लोडर को एहसास होगा, कि बाहरी लिंकेज के साथ पहले से ही "फू" है।

इससे भी बदतर: चरण 3 संकलक अनुकूलन, प्लगइन लोड तंत्र, आदि के आधार पर अलग तरह से व्यवहार कर सकता है।

मुझे दो प्लगइन्स में दो सहायक कार्यों (एक ही नाम, अलग व्यवहार) के साथ एक बार यह मुद्दा मिला था। उन्हें स्थिर घोषित करने से समस्या हल हो गई।


दो प्लग-इन के बीच नाम टकराव के बारे में कुछ अजीब लग रहा था, जिसने मुझे अपने कई DLL में से एक के लिए लिंक मानचित्र की जांच करने के लिए प्रेरित किया, जो बाहरी लिंकेज के साथ m_hDfltHeap को परिभाषित करता है। निश्चित रूप से, यह सभी दुनिया को देखने और उपयोग करने के लिए है, लिंकेज मानचित्र में _m_hDfltHeap के रूप में सूचीबद्ध है। मैं इस तथ्य के बारे में सब भूल गया था।
डेविड ए। ग्रे

4

C99 / GNU99 विनिर्देश के अनुसार:

  • static

    • भंडारण-वर्ग विनिर्देशक है

    • डिफ़ॉल्ट रूप से फ़ाइल स्तर गुंजाइश की वस्तुओं में बाहरी लिंकेज होता है

    • स्टैटिक स्पेसिफिक के साथ फाइल लेवल स्कोप की वस्तुओं में इंटरनल लिंकेज होता है
  • const

    • टाइप-क्वालिफायर है (प्रकार का एक हिस्सा है)

    • तत्काल बाएं उदाहरण पर लागू किया गया कीवर्ड - यानी

      • MyObj const * myVar; - योग्य वस्तु प्रकार को अयोग्य करने के लिए अयोग्य सूचक

      • MyObj * const myVar; - अयोग्य वस्तु प्रकार के लिए योग्य पात्र कांस्टेबल

    • सबसे बड़ा उपयोग - ऑब्जेक्ट प्रकार पर लागू होता है, चर नहीं

      • const MyObj * myVar; - योग्य वस्तु प्रकार को अयोग्य करने के लिए अयोग्य सूचक

इस प्रकार:

static NSString * const myVar; - आंतरिक लिंकेज के साथ अपरिवर्तनीय स्ट्रिंग के लिए निरंतर सूचक।

staticकीवर्ड की अनुपस्थिति परिवर्तनशील नाम को वैश्विक बनाएगी और आवेदन के भीतर नाम के टकराव को जन्म दे सकती है।


4

C ++ 17 inlineचर

यदि आप "C ++ कास्ट स्टैटिक" गॉगल करते हैं, तो यह बहुत संभावना है कि आप वास्तव में क्या उपयोग करना चाहते हैं C ++ 17 इनलाइन चर

यह भयानक C ++ 17 फीचर हमें इसकी अनुमति देता है:

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_i == notmain_func());
    assert(notmain_i == 42);
}

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline constexpr int notmain_i = 42;

const int* notmain_func();

#endif

notmain.cpp

#include "notmain.hpp"

const int* notmain_func() {
    return &notmain_i;
}

संकलित करें और चलाएं:

g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main

गिटहब ऊपर

यह भी देखें: इनलाइन चर कैसे काम करते हैं?

इनलाइन चरों पर C ++ मानक

C ++ मानक गारंटी देता है कि पते समान होंगे। C ++ 17 N4659 मानक ड्राफ्ट 10.1.6 "इनलाइन विनिर्देशक":

6 बाहरी लिंक के साथ एक इनलाइन फ़ंक्शन या चर सभी अनुवाद इकाइयों में एक ही पता होगा।

cppreference https://en.cppreference.com/w/cpp/language/inline बताता है कि अगर staticनहीं दिया गया है, तो इसका बाहरी संबंध है।

जीसीसी इनलाइन चर कार्यान्वयन

हम यह देख सकते हैं कि इसे किस प्रकार लागू किया जाता है:

nm main.o notmain.o

जिसमें है:

main.o:
                 U _GLOBAL_OFFSET_TABLE_
                 U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
                 U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i

notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i

और man nmइसके बारे में कहते हैं u:

"यू" प्रतीक एक अद्वितीय वैश्विक प्रतीक है। यह ईएलएफ प्रतीक बाइंडिंग के मानक सेट के लिए एक जीएनयू विस्तार है। इस तरह के प्रतीक के लिए गतिशील लिंकर यह सुनिश्चित करेगा कि पूरी प्रक्रिया में इस नाम और उपयोग के प्रकार के साथ सिर्फ एक प्रतीक है।

इसलिए हम देखते हैं कि इसके लिए एक समर्पित ईएलएफ एक्सटेंशन है।

प्री-सी ++ 17: extern const

C ++ 17 से पहले, और C में, हम एक के साथ एक बहुत ही समान प्रभाव प्राप्त कर सकते हैं extern const, जो एकल मेमोरी स्थान का उपयोग करेगा।

नीचे की ओर inlineहैं:

  • constexprइस तकनीक से वैरिएबल बनाना संभव नहीं है , केवल यह inlineअनुमति देता है: कॉन्स्ट्रेक्ट एक्सटर्नल कैसे घोषित करें?
  • यह कम सुरुचिपूर्ण है क्योंकि आपको हेडर और सीपीपी फ़ाइल में चर को अलग से घोषित करना और परिभाषित करना है

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_i == notmain_func());
    assert(notmain_i == 42);
}

notmain.cpp

#include "notmain.hpp"

const int notmain_i = 42;

const int* notmain_func() {
    return &notmain_i;
}

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

extern const int notmain_i;

const int* notmain_func();

#endif

गिटहब ऊपर

प्री-सी ++ 17 हेडर केवल विकल्प

ये externसमाधान के रूप में अच्छे नहीं हैं, लेकिन वे काम करते हैं और केवल एक ही मेमोरी स्थान लेते हैं:

एक constexprफ़ंक्शन, क्योंकि constexprइसका तात्पर्य inlineinline प्रत्येक अनुवाद इकाई पर दिखने वाली परिभाषा (बलों) से है और अनुमति देता है :

constexpr int shared_inline_constexpr() { return 42; }

और मैं शर्त लगाता हूं कि किसी भी सभ्य संकलक कॉल को इनलाइन करेगा।

आप निम्न के रूप में constया constexprस्थिर चर का भी उपयोग कर सकते हैं :

#include <iostream>

struct MyClass {
    static constexpr int i = 42;
};

int main() {
    std::cout << MyClass::i << std::endl;
    // undefined reference to `MyClass::i'
    //std::cout << &MyClass::i << std::endl;
}

लेकिन आप इसका पता लेने जैसी चीजें नहीं कर सकते हैं, वरना यह ओडीआर-यूज़ हो जाता है, इसे भी देखें: कॉन्स्ट्रेक्स स्टैटिक उत्पादों को परिभाषित करना

सी

C में स्थिति C ++ पूर्व C ++ 17 जैसी ही है, मैंने इस पर एक उदाहरण अपलोड किया है: C में "स्थिर" का क्या अर्थ है?

फर्क सिर्फ इतना है कि C ++, है constतात्पर्य staticवैश्विक के लिए, लेकिन यह सी में नहीं करता है: बनाम `` const` स्थिर const` की सी ++ अर्थ विज्ञान

इसे पूरी तरह से इनलाइन करने का कोई तरीका?

TODO: क्या किसी भी मेमोरी का उपयोग किए बिना, चर को पूरी तरह से इनलाइन करने का कोई तरीका है?

प्रीप्रोसेसर जितना पसंद करता है।

इसके लिए किसी तरह की आवश्यकता होगी:

  • यदि चर का पता लिया जाए तो मना करना या पता लगाना
  • उस जानकारी को ELF ऑब्जेक्ट फ़ाइलों में जोड़ें, और LTO को इसे ऑप्टिमाइज़ करने दें

सम्बंधित:

उबंटू 18.10, जीसीसी 8.2.0 में परीक्षण किया गया।


2

हां, यह एक मॉड्यूल को दूसरे मॉड्यूल से एक मॉड्यूल में छुपाता है। C ++ में, मैं इसका उपयोग तब करता हूं जब मैं नहीं चाहता / एक .h फ़ाइल को बदलने की आवश्यकता होती है जो अन्य फ़ाइलों के अनावश्यक पुनर्निर्माण को ट्रिगर करेगी। इसके अलावा, मैंने स्टैटिक को पहले रखा:

static const int foo = 42;

इसके अलावा, इसके उपयोग के आधार पर, संकलक इसके लिए भंडारण भी आवंटित नहीं करेगा और जहां यह उपयोग किया जाता है, वहां बस "इनलाइन"। स्थिर के बिना, संकलक यह नहीं मान सकता है कि इसका उपयोग कहीं और नहीं किया जा रहा है और इनलाइन नहीं हो सकता है।


2

यह आईआईए वैश्विक निरंतर दृश्यमान / केवल संकलन मॉड्यूल (.cpp फ़ाइल) में सुलभ है। इस उद्देश्य के लिए स्थैतिक का उपयोग करते हुए BTW को हटा दिया जाता है। एक अनाम नाम और एक एनम का बेहतर उपयोग करें:

namespace
{
  enum
  {
     foo = 42
  };
}

यह संकलक को एक स्थिर और इस तरह के बाधा अनुकूलन के रूप में फू का इलाज नहीं करने के लिए मजबूर करेगा।
निल्स पिपेनब्रिनक

Enums का मान हमेशा स्थिर होता है इसलिए मैं नहीं देखता कि यह किसी भी अनुकूलन में कैसे बाधा
डालेगा

आह - सच .. मेरी त्रुटि। सोचा कि आपने एक साधारण अंतर-चर का उपयोग किया है।
निल्स पिपेनब्रिंक

रोसकोतो, मुझे स्पष्ट नहीं है कि enumइस संदर्भ में क्या लाभ है। विस्तृत करने के लिए परवाह? इस तरह enumsआम तौर पर केवल मूल्य के लिए किसी भी स्थान का आवंटन (हालांकि आधुनिक compilers इस की जरूरत नहीं है से संकलक को रोकने के लिए उपयोग किया जाता है enumइसके लिए हैक) और मूल्य के लिए संकेत के निर्माण को रोकने के लिए।
कोनराड रूडोल्फ

कोनराड, इस मामले में एक एनम का उपयोग करने में आपको क्या समस्या है? Enums का उपयोग तब किया जाता है जब आपको निरंतर चींटियों की आवश्यकता होती है जो वास्तव में है।
रोजकोटो

1

इसे निजी बनाने का मतलब अभी भी हेडर में दिखाई देगा। मैं "सबसे कमजोर" तरीके का उपयोग करता हूं जो काम करता है। स्कॉट मेयर्स के इस क्लासिक लेख को देखें: http://www.ddj.com/cpp/184401197 (यह कार्यों के बारे में है, लेकिन यहां भी लागू किया जा सकता है)।

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