c++ - लूप, अच्छी प्रैक्टिस या बुरी प्रैक्टिस के अंदर चर घोषित करना?




loops variable-declaration (3)

प्रश्न # 1: एक लूप के अंदर एक चर को एक अच्छा अभ्यास या बुरी आदत घोषित कर रहा है?

मैंने अन्य धागे पढ़े हैं कि प्रदर्शन प्रदर्शन मुद्दा है या नहीं (अधिकतर कहा गया नहीं), और आपको हमेशा वेरिएबल्स घोषित करना चाहिए जहां वे उपयोग किए जा रहे हैं। मैं क्या सोच रहा हूं कि यह टालना चाहिए या नहीं, अगर इसे वास्तव में पसंद किया जाता है।

उदाहरण:

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

   cout << someString;
}

प्रश्न # 2: क्या अधिकांश कंपाइलर्स का एहसास है कि चर पहले ही घोषित कर दिया गया है और बस उस हिस्से को छोड़ दें, या क्या यह वास्तव में हर बार स्मृति में इसके लिए एक जगह बनाता है?


आम तौर पर, इसे बहुत करीब रखने के लिए यह एक बहुत अच्छा अभ्यास है।

कुछ मामलों में, ऐसे प्रदर्शन पर विचार किया जाएगा जो प्रदर्शन के रूप में लूप के चर को खींचने का औचित्य साबित करता है।

आपके उदाहरण में, कार्यक्रम हर बार स्ट्रिंग बनाता है और नष्ट कर देता है। कुछ पुस्तकालय एक छोटे स्ट्रिंग अनुकूलन (एसएसओ) का उपयोग करते हैं, इसलिए कुछ मामलों में गतिशील आवंटन से बचा जा सकता है।

मान लीजिए कि आप उन अनावश्यक रचनाओं / आवंटन से बचना चाहते हैं, तो आप इसे इस प्रकार लिखेंगे:

for (int counter = 0; counter <= 10; counter++) {
   // compiler can pull this out
   const char testing[] = "testing";
   cout << testing;
}

या आप निरंतर बाहर खींच सकते हैं:

const std::string testing = "testing";
for (int counter = 0; counter <= 10; counter++) {
   cout << testing;
}

क्या अधिकांश कंपाइलर्स का एहसास है कि चर पहले ही घोषित कर दिया गया है और बस उस हिस्से को छोड़ दें, या क्या यह वास्तव में हर बार स्मृति में इसके लिए एक जगह बनाता है?

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

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

प्रत्येक मामले में अनावश्यक प्रतिलिपि की आवश्यकता होगी, और गतिशील आवंटन और नि: शुल्क होगा यदि चर एसएसओ चरित्र गणना के लिए थ्रेसहोल्ड के ऊपर बैठता है (और एसएसओ आपकी एसडीडी लाइब्रेरी द्वारा कार्यान्वित किया जाता है)।

यह कर रहा हूं:

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

प्रत्येक पुनरावृत्ति पर वर्णों की भौतिक प्रतिलिपि की आवश्यकता होगी, लेकिन फ़ॉर्म के परिणामस्वरूप एक गतिशील आवंटन हो सकता है क्योंकि आप स्ट्रिंग असाइन करते हैं और कार्यान्वयन को देखना चाहिए कि स्ट्रिंग के बैकिंग आवंटन का आकार बदलने की आवश्यकता नहीं है। बेशक, आप इस उदाहरण में ऐसा नहीं करेंगे (क्योंकि कई बेहतर विकल्प पहले ही प्रदर्शित किए जा चुके हैं), लेकिन जब आप स्ट्रिंग या वेक्टर की सामग्री बदलती हैं तो आप इसे मान सकते हैं।

तो आप उन सभी विकल्पों (और अधिक) के साथ क्या करते हैं? इसे डिफ़ॉल्ट के रूप में बहुत करीब रखें - जब तक कि आप लागत को अच्छी तरह से समझ न लें और जानें कि आपको कब विचलित होना चाहिए।


मैंने जेरेमीआरआर के सवालों के जवाब देने के लिए पोस्ट नहीं किया (जैसा कि उनका पहले से ही उत्तर दिया गया है); इसके बजाय, मैंने केवल एक सुझाव देने के लिए पोस्ट किया।

जेरेमीआरआर को, आप यह कर सकते हैं:

{
  string someString = "testing";   

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

  // The variable is in scope.
}

// The variable is no longer in scope.

मुझे नहीं पता कि क्या आपको एहसास है (मैंने पहली बार प्रोग्रामिंग शुरू नहीं किया था), कि ब्रैकेट्स (जब तक वे जोड़े में हैं) को कोड के भीतर कहीं भी रखा जा सकता है, न कि "अगर", "के लिए", " जबकि "आदि

मेरा कोड माइक्रोसॉफ्ट विजुअल सी ++ 2010 एक्सप्रेस में संकलित है, इसलिए मुझे पता है कि यह काम करता है; साथ ही, मैंने उन ब्रैकेट्स के बाहर चर का उपयोग करने का प्रयास किया है, जिन्हें परिभाषित किया गया था और मुझे एक त्रुटि मिली, इसलिए मुझे पता है कि चर "नष्ट" था।

मुझे नहीं पता कि यह इस विधि का उपयोग करने के लिए बुरी आदत है, क्योंकि बहुत से लेबल किए गए ब्रैकेट्स कोड को अपठनीय बना सकते हैं, लेकिन शायद कुछ टिप्पणियां चीजों को साफ़ कर सकती हैं।


सी ++ के लिए यह निर्भर करता है कि आप क्या कर रहे हैं। ठीक है, यह बेवकूफ कोड है लेकिन कल्पना करो

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 सेकंड की आवश्यकता होती है।

जब तक आप myOtherFunc का आउटपुट प्राप्त नहीं करेंगे तब तक आपको 5 सेकंड की आवश्यकता होगी।

बेशक, यह एक पागल उदाहरण है।

लेकिन यह दिखाता है कि यह एक प्रदर्शन मुद्दा बन सकता है जब प्रत्येक लूप एक ही निर्माण किया जाता है जब निर्माता और / या विनाशक को कुछ समय की आवश्यकता होती है।





variable-declaration