c++ - स्थिर सूचक एक निरंतर अभिव्यक्ति क्यों नहीं हो सकता है?




pointers c++11 (2)

यह थोड़ा और जटिल है। सी ++ 03 और सी ++ 11 में, &var एक निरंतर अभिव्यक्ति है यदि var एक स्थानीय स्थिर / वर्ग स्थैतिक या नामस्थान स्कोप चर है। इसे एक निरंतर अभिव्यक्ति कहा जाता है। उस स्थिर अभिव्यक्ति के साथ कक्षा स्थिर या नामस्थान स्कोप पॉइंटर चर प्रारंभ करना किसी भी कोड को चलाने से पहले किया जाना चाहिए (स्थिर प्रारंभिक चरण), क्योंकि यह निरंतर अभिव्यक्ति है।

हालांकि केवल सी ++ 11 में, एक कॉन्स्टेक्स पॉइंटर वैरिएबल जो पता &var को स्टोर करता है, को एड्रेस निरंतर अभिव्यक्ति के रूप में भी इस्तेमाल किया जा सकता है और केवल सी ++ 11 में, आप एक एड्रेस निरंतर अभिव्यक्ति को अव्यवस्थित कर सकते हैं (असल में, आप और भी कम कर सकते हैं - यहां तक ​​कि स्थानीय सरणी तत्व पते भी हैं, लेकिन चलो इसे स्थैतिक रखें) और यदि यह निरंतर अभिन्न चर को संदर्भित करता है जो पूर्ववर्ती या कॉन्स्टेक्स चर से पहले शुरू होता है, तो आपको फिर से निरंतर अभिव्यक्ति मिलती है (प्रकार और मान श्रेणी के आधार पर, निरंतर प्रकार अभिव्यक्ति भिन्न हो सकती है)। इस प्रकार, निम्नलिखित मान्य सी ++ 11 है:

int const x = 42;
constexpr int const *px = &x;

// both the value of "px" and the value of "*px" are prvalue constant expressions
int array[*px];
int main() { return sizeof(array); }

यदि हां, तो पॉइंटर निरंतर अभिव्यक्ति क्यों नहीं हो सकता है? यदि नहीं, तो उपर्युक्त प्रोग्राम क्यों संकलित नहीं करते हैं?

यह मानक के शब्दों में एक ज्ञात सीमा है - यह वर्तमान में अन्य प्रकार के टेम्पलेट पैरामीटर को तर्क प्रकार के टेम्पलेट पैरामीटर के लिए तर्क या & object रूप में अनुमति देता है। हालांकि संकलक बहुत अधिक करने में सक्षम होना चाहिए।

निम्नलिखित प्रोग्राम संकलित करता है:

template <const int * P>
class Test{};

extern const int var = 42; //extern needed to force external linkage

int main()
{
    Test<&var> test;
}

हालांकि, यह नहीं है, जो मेरे लिए आश्चर्यचकित है:

template <const int * P>
class Test{};

extern const int var = 42; //extern needed to force external linkage
extern const int * const ptr = &var; //extern needed to force external linkage
int main()
{
    Test<ptr> test; //FAIL! Expected constant expression.
}

वैकल्पिक उदाहरण:

int main()
{
   const int size = 42;
   int ok[*&size]; //OK

   const int * const pSize = &size;
   int fail[*pSize]; //FAIL
}

मैंने निष्कर्ष निकाला है कि एक सूचक सिर्फ स्थिर अभिव्यक्ति नहीं हो सकता है चाहे वह स्थिर है या निरंतर अभिव्यक्ति के साथ प्रारंभ किया गया हो।

प्रशन:

  1. क्या मेरा निष्कर्ष सच है?
  2. यदि हां, तो पॉइंटर निरंतर अभिव्यक्ति क्यों नहीं हो सकता है? यदि नहीं, तो उपर्युक्त प्रोग्राम क्यों संकलित नहीं करते हैं?
  3. क्या सी ++ 0x (सी ++ 11, यदि आप करेंगे) कुछ भी बदलते हैं?

किसी भी अंतर्दृष्टि के लिए धन्यवाद!


समस्या यह है कि आपका सी ++ प्रोग्राम स्मृति में किसी भी बिंदु पर लोड किया जा सकता है, और इसलिए जब भी आप प्रोग्राम चलाते हैं तो वैश्विक var का पता भिन्न हो सकता है। यदि आप अपना प्रोग्राम दो बार चलाते हैं तो क्या होता है? var स्पष्ट रूप से दो अलग-अलग स्थानों में है।

इससे भी बदतर, आपके उदाहरण में, आप ढेर पर एक चर का पता लेते हैं! इसे देखो:

void myfunction( unsigned int depth) {
     const int myvar = depth;
     const int * const myptr = &myvar;
     if (depth)
         myfunction(depth-1);
}

यदि मुख्य कॉल myfunction (3), तो 3 myvars अलग स्थानों पर बनाए जाते हैं। संकलन समय के बारे में जानने का कोई तरीका नहीं है कि कितने माईवर्स बनाए जाते हैं, वहां बहुत कम सटीक स्थान हैं।

अंत में: परिवर्तनीय होने के लिए एक चर घोषित करने का अर्थ है: "मैं वादा करता हूं", और इसका मतलब यह नहीं है कि संकलन समय स्थिर है। यह उदाहरण देखें:

int main(int argc, char** argv) {
    const int cargc = argc;
    char* myargs[cargc]; //the size is constant, but not a _compile time_ constant.
}




constant-expression