क्रॉस आरंभीकरण के संकेत क्या हैं?


84

निम्नलिखित कोड पर विचार करें:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
    switch(i) {
        case 1:
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

जी ++ शिकायत करता है crosses initialization of 'int r'। मेरे प्रश्न हैं:

  1. क्या है crosses initialization?
  2. पहला इनिलाइज़र x + yसंकलन क्यों पास करता है , लेकिन बाद वाला विफल हो गया?
  3. तथाकथित समस्याएं क्या हैं crosses initialization?

मुझे पता है कि मुझे इसका दायरा निर्दिष्ट करने के लिए कोष्ठक का उपयोग करना चाहिए r, लेकिन मैं यह जानना चाहता हूं कि, उदाहरण के लिए, गैर-पॉड को बहु-मामले स्विच स्टेटमेंट में क्यों नहीं परिभाषित किया जा सकता है।


1
मेरी समझ, नीचे दिए गए जवाबों के लिए, बिंदु 3 के लिए यह है कि यह त्रुटि c ++ का अत्यधिक प्रतिबंध है। यदि लेबल के बाद r का उपयोग नहीं किया जाता है, तो कोई प्रभाव नहीं होता है (यहां तक ​​कि अगर उदाहरण r का उपयोग करता है, तो इसे 2 स्थिति में हटाया जा सकता है और कंपाइलर एक ही त्रुटि देगा)। बेहतर प्रमाण यह है कि सी में इसकी अनुमति है, और यहां तक ​​कि सी 11 में भी।
कैलेंडोआ

जवाबों:


95

वाला संस्करण int r = x + y;या तो संकलन नहीं करेगा।

समस्या यह है कि rइसके आरंभिक निष्पादन के बिना दायरे में आना संभव है । यदि आपने इनिशियलाइज़र को पूरी तरह से हटा दिया है तो कोड ठीक संकलित करेगा (यानी लाइन पढ़ेगी int r;)।

सबसे अच्छी चीज जो आप कर सकते हैं वह है चर के दायरे को सीमित करना। इस तरह आप संकलक और पाठक दोनों को संतुष्ट करेंगे।

switch(i)
{
case 1:
    {
        int r = 1;
        cout << r;
    }
    break;
case 2:
    {
        int r = x - y;
        cout << r;
    }
    break;
};

मानक कहते हैं (6.7 / 3):

एक ब्लॉक में स्थानांतरित करना संभव है, लेकिन इस तरह से नहीं कि प्रारंभिककरण के साथ घोषणाओं को बायपास करें। एक प्रोग्राम जो उस बिंदु से कूदता है जहां स्वचालित भंडारण अवधि के साथ एक स्थानीय चर एक बिंदु के दायरे में नहीं है, जहां यह गुंजाइश है, यह तब तक बीमार है जब तक कि चर में POD प्रकार (3.9) न हो और एक इनिशलाइज़र (8.5) के बिना घोषित हो।


लेकिन मेरा G ++ अनुमति देता है int r = x + y
जिचाओ

10
खैर, मेरा जी ++ नहीं करता है। फिर से जांचें या कंपाइलर को अपग्रेड करें।
अवकर

धन्यवाद, जो मेरे लिए मददगार था। मुझे लगता है कि सी कंपाइलर कुछ कोड के बाद भी डिक्लेरेशन नहीं आने देता । जाहिरा तौर पर C99 अनुमति देता है कि हालांकि ... stackoverflow.com/questions/7859424/…
m-ric

36

आपको caseइसे दायरे में देने के लिए कोष्ठक की सामग्री डालनी चाहिए , इस तरह से आप इसके अंदर स्थानीय चर घोषित कर सकते हैं:

switch(i) {
    case 1:
        {
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
        }
        break;
    case 2:
        ...
        break;
};

3

एक ब्लॉक में स्थानांतरित करना संभव है, लेकिन इस तरह से नहीं कि प्रारंभिककरण के साथ घोषणाओं को बायपास करें। एक प्रोग्राम जो उस बिंदु से कूदता है जहां स्वचालित भंडारण अवधि के साथ एक स्थानीय चर एक बिंदु के दायरे में नहीं होता है, जहां यह गुंजाइश है कि यह तब तक बीमार है जब तक कि चर में POD का प्रकार न हो और इसे बिना इनिशलाइज़र के घोषित न किया जाए।

[Example: Code:

void f()
{
  // ...
  goto lx;    // ill-formed: jump into scope of `a'
  // ...
 ly:
    X a = 1;
  // ...
 lx:
   goto ly;    // ok, jump implies destructor
 // call for `a' followed by construction
 // again immediately following label ly
}

--end example]

स्विच स्टेटमेंट की स्थिति से केस लेबल में स्थानांतरण को इस संबंध में एक छलांग माना जाता है।


1
ढेर अतिप्रवाह में आपका स्वागत है। आपको अपने उद्धरणों के लिए स्रोत प्रदान करने चाहिए, यह C ++ 03: 6.7 / 3 है। यह भी वही होता है जो मैंने अपने उत्तर में उद्धृत किया था।
अवकर

0

मेरा सुझाव है कि आप वक्तव्य rसे पहले अपने चर को बढ़ावा switchदें। यदि आप caseब्लॉकों में एक चर का उपयोग करना चाहते हैं , (या एक ही चर नाम लेकिन विभिन्न उपयोग), तो स्विच स्टेटमेंट से पहले इसे परिभाषित करें:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
// Define the variable before the switch.
    int r;
    switch(i) {
        case 1:
            r = x + y
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

एक लाभ यह है कि कंपाइलर को प्रत्येक ब्लॉक में स्थानीय आवंटन (स्टैक पर उर्फ ​​धक्का) नहीं करना पड़ता है case

इस दृष्टिकोण का एक दोष यह है कि जब मामले अन्य मामलों में "गिर जाते हैं" (अर्थात बिना उपयोग किए break), क्योंकि चर का पिछला मान होगा।


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