ক্রস আরম্ভের লক্ষণগুলি কী কী?


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তবে আমি কেন জানতে চাই, উদাহরণস্বরূপ, কেন নন-পিওডি মাল্টি-কেস সুইচ বিবৃতিতে সংজ্ঞায়িত করা যায়নি।


4
আমার বোঝার জন্য নীচের উত্তরগুলি দেওয়া হয়েছে, পয়েন্ট 3 এর জন্য এই ত্রুটিটি সি ++ এর অত্যধিক বিধিনিষেধ। যদি আর লেবেলের পরে ব্যবহার না করা হয় তবে কোনও প্রভাব পড়বে না (এমনকি যদি উদাহরণটি আর ব্যবহার করে তবে এটি 2 ক্ষেত্রে অপসারণ করা যেতে পারে এবং সংকলকটি একই ত্রুটি দেয়)। আরও ভাল প্রমাণ হ'ল এটি সি এবং এমনকি সি 11 এ অনুমোদিত।
ক্যালান্দোয়া

উত্তর:


96

সহ সংস্করণটিও 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) ব্যতীত ঘোষিত না হয় ill


তবে আমার জি ++ অনুমতি দেয় int r = x + y
জিচাও

10
ভাল, আমার জি ++ না। আবার চেক করুন বা সংকলকটি আপগ্রেড করুন।
অবাকর

ধন্যবাদ, এটি আমার পক্ষে সহায়ক ছিল। আমি মনে করি যে সি সংকলক এমনকি কিছু কোডের পরে ঘোষণা আসতে দেয় না । দৃশ্যত C99 অনুমতি দেয় যদিও ... stackoverflow.com/questions/7859424/...
M-রিক

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]

একটি স্যুইচ স্টেটমেন্টের শর্ত থেকে কেস লেবেলে স্থানান্তর করা এই ক্ষেত্রে এক লাফ হিসাবে বিবেচিত হয়।


4
স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম। আপনার উদ্ধৃতিগুলির জন্য উত্স সরবরাহ করা উচিত, এটি সি ++ 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) "পড়ে" যায় , কারণ ভেরিয়েবলের আগের মান থাকবে।


4
আমি অন্য উপায়ে এটি করার পরামর্শ দেব। সংকলক উভয় ক্ষেত্রেই "স্থানীয় বরাদ্দ" সম্পাদন করতে হবে না (এবং বাস্তবে এটি হবে না)।
অবাকর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.