c++ - Loops, ভাল অনুশীলন বা খারাপ অনুশীলন ভিতরে ভেরিয়েবল ঘোষণা?




variable-declaration (3)

প্রশ্ন # 1: একটি লুপ ভিতরে একটি পরিবর্তনশীল ঘোষণা একটি ভাল অভ্যাস বা খারাপ অভ্যাস?

আমি অন্য কোন থ্রেড পড়েছি কিনা একটি পারফরমেন্স ইস্যু আছে কিনা (সর্বাধিক বলা হয়নি), এবং আপনি সর্বদা যেখানে ভেরিয়েবলগুলি ব্যবহার করতে যাচ্ছেন তার কাছাকাছি ডিক্লেয়ার করা উচিত। আমি কি ভাবছি যে এটিকে এড়িয়ে যাওয়া উচিত নাকি এটি আসলে পছন্দসই।

উদাহরণ:

for(int counter = 0; counter <= 10; counter++)
{
   string someString = "testing";

   cout << someString;
}

প্রশ্ন # 2: অধিকাংশ কম্পাইলার বুঝতে পারছেন যে পরিবর্তনশীল ইতিমধ্যে ঘোষিত হয়েছে এবং শুধুমাত্র সেই অংশটি এড়িয়ে যান, নাকি এটি আসলেই স্মৃতিতে এটির জন্য একটি স্পট তৈরি করে?


আমি জেরেমিআরআর এর প্রশ্নের জবাব দিতে পোস্ট করিনি (যেমন তারা ইতিমধ্যে উত্তর পেয়েছে); পরিবর্তে, আমি একটি প্রস্তাব দিতে নিছক পোস্ট।

জেরেমিআরআর করতে, আপনি এটি করতে পারেন:

{
  string someString = "testing";   

  for(int counter = 0; counter <= 10; counter++)
  {
    cout << someString;
  }

  // The variable is in scope.
}

// The variable is no longer in scope.

আমি বুঝতে পারছি না যদি আপনি বুঝতে পারছেন (আমি কখন প্রথম প্রোগ্রামিং শুরু করি নি), যে বন্ধনীগুলি (যতক্ষণ পর্যন্ত তারা জোড়া থাকে) কোডের মধ্যে যে কোন স্থানে স্থাপন করা যেতে পারে, কেবলমাত্র "if", "for", " যখন ", ইত্যাদি

মাইক্রোসফ্ট ভিসুয়াল সি ++ ২010 এক্সপ্রেসে আমার কোড কম্পাইল হয়েছে, তাই আমি জানি এটি কাজ করে; এছাড়াও, আমি ভেরিয়েবল ব্যবহার করতে চেষ্টা করেছি যাতে এটি সংজ্ঞায়িত করা হয়েছে এবং আমি একটি ত্রুটি পেয়েছি, তাই আমি জানি যে পরিবর্তনশীল "ধ্বংস" ছিল।

এই পদ্ধতিটি ব্যবহার করার জন্য এটি খারাপ অভ্যাস কিনা তা আমি জানি না, কারণ অনেকগুলি অননুমোদিত বন্ধনী কোডটিকে দ্রুত পাঠ্যহীন করে তুলতে পারে তবে হয়ত কিছু মন্তব্য জিনিসগুলি পরিষ্কার করতে পারে।


এই চমৎকার অনুশীলন।

Loops ভিতরে ভেরিয়েবল তৈরি করে, আপনি তাদের সুযোগ লুপ ভিতরে সীমাবদ্ধ কিনা তা নিশ্চিত করুন। এটি রেফারেন্স করা যায় না এবং লুপের বাইরেও বলা যায় না।

এই পথে:

  • ভেরিয়েবলের নামটি যদি কিছুটা "জেনেরিক" (যেমন "i") হয়, তাহলে এটি অন্য কোনও নামের সাথে অন্য কোনও পরিবর্তনশীলের সাথে আপনার কোডে পরেও যুক্ত করার ঝুঁকি থাকে না (এটি GCC- এ -Wshadow সতর্কবার্তা নির্দেশনা ব্যবহার করেও কমিয়ে আনা যেতে পারে) )

  • কম্পাইলার জানেন যে পরিবর্তনশীল সুযোগটি লুপের ভিতরে সীমাবদ্ধ, এবং সেই কারণে ভেরিয়েবলটি অন্যত্র উল্লিখিত ভুলের মাধ্যমে সঠিক ত্রুটি বার্তা প্রদান করবে।

  • অন্তত কিন্তু অন্তত না, কিছু ডেডিকেটেড অপ্টিমাইজেশান কম্পাইলার (সবচেয়ে গুরুত্বপূর্ণভাবে বরাদ্দ নিবন্ধন) দ্বারা আরও দক্ষতার সাথে সম্পাদন করা যেতে পারে, কারণ এটি জানেন যে পরিবর্তনশীল লুপের বাইরে ব্যবহার করা যাবে না। উদাহরণস্বরূপ, পরবর্তী পুনরায় ব্যবহারের জন্য ফলাফল সংরক্ষণ করার কোন প্রয়োজন নেই।

সংক্ষেপে, আপনি এটা করতে অধিকার।

উল্লেখ্য যে পরিবর্তনশীল প্রতিটি লুপ এর মধ্যে তার মান বজায় রাখা অনুমিত হয় না । এই ক্ষেত্রে, আপনি প্রতিবার এটি আরম্ভ করতে হবে। আপনি একটি বড় ব্লকও তৈরি করতে পারেন, যা লুপকে অন্তর্ভুক্ত করে, যার একমাত্র উদ্দেশ্য ভেরিয়েবলগুলি ঘোষণা করা যা অবশ্যই তাদের একটি লুপ থেকে অন্যের মান বজায় রাখতে হবে। এই সাধারণত লুপ পাল্টা নিজেই অন্তর্ভুক্ত।

{
    int i, retainValue;
    for (i=0; i<N; i++)
    {
       int tmpValue;
       /* tmpValue is uninitialized */
       /* retainValue still has its previous value from previous loop */

       /* Do some stuff here */
    }
    /* Here, retainValue is still valid; tmpValue no longer */
}

প্রশ্ন # 2 জন্য: ফাংশন বলা হয়, একবার পরিবর্তনশীল বরাদ্দ করা হয়। প্রকৃতপক্ষে, একটি বরাদ্দ দৃষ্টিকোণ থেকে, এটি (প্রায়) ফাংশনের শুরুতে পরিবর্তনশীল ঘোষণা হিসাবে একই। শুধুমাত্র পার্থক্য হল সুযোগ: পরিবর্তনশীল লুপ বাইরে ব্যবহার করা যাবে না। এটি এমনকি সম্ভব যে পরিবর্তনশীল বরাদ্দ করা হয় না, কিছু মুক্ত স্লট পুনরায় ব্যবহার করুন (অন্যান্য পরিবর্তনশীল যার সুযোগ শেষ হয়েছে)।

সীমিত এবং আরো সুনির্দিষ্ট সুযোগ সঙ্গে আরো সঠিক অপ্টিমাইজেশান। কিন্তু আরো গুরুত্বপূর্ণ, কোডটি অন্যান্য অংশগুলি পড়ার বিষয়ে চিন্তা করার জন্য কম রাজ্যের (অর্থাত্ ভেরিয়েবল) সাথে আপনার কোড নিরাপদ করে তোলে।

এটি এমনকি একটি if(){...} ব্লকের বাইরেও সত্য। সাধারণত, পরিবর্তে:

    int result;
    (...)
    result = f1();
    if (result) then { (...) }
    (...)
    result = f2();
    if (result) then { (...) }

এটা লিখতে নিরাপদ:

    (...)
    {
        int const result = f1();
        if (result) then { (...) }
    }
    (...)
    {
        int const result = f2();
        if (result) then { (...) }
    }

পার্থক্য ক্ষুদ্র মনে হতে পারে, বিশেষ করে যেমন একটি ছোট উদাহরণ। কিন্তু বৃহত্তর কোড বেসে এটি সাহায্য করবে: এখন f1() থেকে f2() ব্লকের কিছু result মান পরিবহন করার কোন ঝুঁকি নেই। প্রতিটি result কঠোরভাবে তার নিজস্ব সুযোগ সীমিত, তার ভূমিকা আরো সঠিক করে তোলে। একজন সমীক্ষার দৃষ্টিকোণ থেকে, এটি অনেক নিকৃষ্ট, কারণ তার সম্পর্কে দীর্ঘস্থায়ী অবস্থা ভেরিয়েবল কম এবং ট্র্যাক করার জন্য রয়েছে।

এমনকি কম্পাইলারও আরও ভালভাবে সাহায্য করবে: ভবিষ্যতে, কিছু ভুল কোড পরিবর্তন করার পরে, result সঠিকভাবে f2() দিয়ে সূচনা করা হয় না। দ্বিতীয় সংস্করণ কেবল কম্পাইল সময় (পরিষ্কার সময় থেকে ভালো উপায়) এ একটি স্পষ্ট ত্রুটি বার্তা বলার কাজ করতে অস্বীকার করবে। প্রথম সংস্করণটি কিছু স্পট করবে না, f1() এর ফলাফলটি কেবল দ্বিতীয়বার পরীক্ষা করা হবে, f2() এর ফলে বিভ্রান্ত হচ্ছে।

পরিপূরক তথ্য

ওপেন সোর্স টুল CppCheck (সি / সি ++ কোডের জন্য একটি স্ট্যাটিক বিশ্লেষণ সরঞ্জাম) ভেরিয়েবলের সর্বোত্তম সুযোগ সম্পর্কিত কিছু চমৎকার ইঙ্গিত সরবরাহ করে।

বরাদ্দের উপর মন্তব্যের প্রতিক্রিয়া: উপরের নিয়ম সি তে সত্য, কিন্তু কিছু C ++ ক্লাসের জন্য এটি হতে পারে না।

স্ট্যান্ডার্ড প্রকার এবং কাঠামোর জন্য, পরিবর্তনশীল আকার কম্পাইলেশন সময় পরিচিত হয়। C তে "নির্মাণ" এর মতো কোনও জিনিস নেই, তাই ভেরিয়েবলের স্থান কেবল স্ট্যাকের (কোনও সূচনা ছাড়াই) বরাদ্দ করা হবে, যখন ফাংশন বলা হয়। তাই একটি লুপ ভিতরে পরিবর্তনশীল ঘোষণা যখন একটি "শূন্য" খরচ আছে।

যাইহোক, সি ++ ক্লাসগুলির জন্য, এই কনস্ট্রাক্টর জিনিস যা আমি প্রায় কম জানি। আমি অনুমান করছি সম্ভবত বরাদ্দ করা যাচ্ছে না, কারণ কম্পাইলারটি একই স্থানটি পুনঃব্যবহারের জন্য যথেষ্ট চতুর হবে, তবে প্রতিটি লুপ পুনরাবৃত্তি শুরু হওয়ার সম্ভাবনা রয়েছে।


সি ++ এর জন্য এটি আপনার উপর নির্ভর করে। ঠিক আছে, এটা মূঢ় কোড কিন্তু কল্পনা

class myTimeEatingClass
{
 public:
 //constructor
      myTimeEatingClass()
      {
          sleep(2000);
          ms_usedTime+=2;
      }
      ~myTimeEatingClass()
      {
          sleep(3000);
          ms_usedTime+=3;
      }
      const unsigned int getTime() const
      {
          return  ms_usedTime;
      }
      static unsigned int ms_usedTime;
};
myTimeEatingClass::ms_CreationTime=0; 
myFunc()
{
    for (int counter = 0; counter <= 10; counter++) {

        myTimeEatingClass timeEater();
        //do something
    }
    cout << "Creating class took "<< timeEater.getTime() <<"seconds at all<<endl;

}
myOtherFunc()
{
    myTimeEatingClass timeEater();
    for (int counter = 0; counter <= 10; counter++) {
        //do something
    }
    cout << "Creating class took "<< timeEater.getTime() <<"seconds at all<<endl;

}

আপনি MyFunc আউটপুট পেতে না হওয়া পর্যন্ত 55 সেকেন্ড অপেক্ষা করবেন। শুধু প্রতিটি লুপ রচয়িতা এবং ধ্বংসকারী একসঙ্গে শেষ করার জন্য 5 সেকেন্ড প্রয়োজন কারণ।

আপনি আমার OtherFunc আউটপুট পেতে না হওয়া পর্যন্ত আপনি 5 সেকেন্ডের প্রয়োজন হবে।

অবশ্যই, এটি একটি পাগল উদাহরণ।

কিন্তু এটি দেখায় যে এটি একটি কর্মক্ষমতা সমস্যা হতে পারে যখন প্রতিটি লুপ একই নির্মাণ করা হয় যখন কন্সট্রাকটর এবং / অথবা ধ্বংসকারীকে কিছু সময়ের প্রয়োজন হয়।





variable-declaration