दरअसल, यदि आप सी ++ करते हैं, तो इसके बजाय ++i
लिखने के लिए उपयोग करना बेहतर होता है। कारण सरल है: i++
एक प्रतिलिपि की आवश्यकता है।
a = ++i; // a is set to the result of i+1
a = i++; // make a copy of i, compute i+1, save the copy of i in a
अनुकूलन के बिना, विधानसभा कोड इस तरह दिखेगा:
a = ++i; a = i++;
MOV eax, (i) MOV eax, (i)
PUSH eax
ADD eax, 1 ADD eax, 1
MOV (i), eax MOV (i), eax
POP eax
MOV (a), eax MOV (a), eax
अब, अनुकूलन के साथ, परिणाम सी में एक ही है जहां ++
ऑपरेटर केवल पूर्णांकों और संकेत करने के लिए लागू होता है।
++
और --
देखते हैं क्योंकि ज्यादातर प्रोसेसर एक INC
और समय सी लिखा गया था पर एक DEC
अनुदेश था। तो अगर आप एक सूचकांक रजिस्टर का उपयोग कर रहा है, इन निर्देशों का लागू किया जाएगा:
char a[256];
...init 'a' in some way...
int sum =0;
for(int i = 0; i < 100; ++i)
{
sum += a[i];
}
यह एक सरल INC
के साथ किया जा सकता है (6502) के रूप में:
LDA #00
LDY #00
LOOP:
CLC
ADC ($80),Y
INY <-- ++i or i++
CPY #100
BCC LOOP
नोट सी में हम है एक और संकेतन एक चर बढ़ाने के लिए:
01:
i += 1;
यह व्यावहारिक है अगर आप 1 से अधिक से रजिस्टर बढ़ाने के लिए की जरूरत है
i += 3;
या रजिस्टर हर बार दोगुना करने के लिए:
i += i; // (equivalent to i *= 2; or i <<= 1; in C++)
प्रश्न: क्यों INC
और DEC
सभी 80x86 के साथ उपयोग नहीं किया जाता है?
ऐसा समय है जब ADD reg, 1
और SUB reg, 1
निर्देश INC reg
और DEC reg
से तेज़ थे।पुराने दिनों में, यह तेज़ था क्योंकि निर्देश छोटा था और हमारे पास कोई कैश नहीं था (या बहुत कम)। आज, या तो निर्देश शायद इसके बारे में है।
नीचे एक टिप्पणी, "सुस्ती" के लिए एक कारण से था FLAGS रजिस्टर:
Intel Optimization Reference, section 3.5.1.1 Use of the INC and DEC Instructions
एक और से
, अधिक वर्तमान टिप्पणी, यह सुस्ती कि इंटेल दस्तावेज़ में संदर्भित तय किया गया है की तरह लग रहा नए प्रोसेसर में। इसलिए इन निर्देशों का उपयोग या गैर-उपयोग लक्ष्य प्रोसेसर पर निर्भर होना चाहिए यदि अग्रिम में जाना जाता है।
के रूप में एक टिप्पणी में phresnel से कहा, i++
और ++i
के बीच का अंतर शायद कई लोगों के लिए स्पष्ट नहीं था। एक पूर्णांक के लिए, अनुकूलन वास्तव में मामूली है और निश्चित रूप से -O0 के साथ भी होगा। हालांकि, सी ++ में, यह एक अलग कहानी है। दोनों वृद्धिशील ऑपरेटरों के साथ एक वर्ग है जो स्पष्ट रूप से दिखा रहा है कि i++
के लिए एक प्रति आवश्यक है (भले ही data_
केवल एक पूर्णांक है, हालांकि उस स्थिति में आप यह भी कर सकते हैं: return data_++
- इसे अभी भी एक अच्छी छिपी हुई प्रति की आवश्यकता है!):
class A
{
public:
A& operator ++() // ++i -- no copy
{
...apply the ++ operation to 'data_'...
return *this; // return a reference to this
}
A operator ++ (int) // i++ -- needs a temporary copy
{
// remember that the 'int' is totally ignored in the function,
// its only purpose is to distinguish '++i' from 'i++'
A copy = *this; // here we need a copy
++*this;
return copy; // and here we return said copy
}
private:
some_type_t data_;
};
ध्यान दें कि आधुनिक सी ++ compilers के रूप में दिए गए मान एक अतिरिक्त प्रति की आवश्यकता के बिना बाहर अनुकूलित किया जा सकता है i++
समारोह में दो प्रतियां नहीं बनाते हैं।
दोनों ही मामलों के बीच अंतर के रूप में दिखाया जा सकता है स्पष्ट रूप से धीमी i++
का उपयोग कर Is there a performance difference between i++ and ++i in C++? (लिंक phresnel ने उल्लेख किया) में वर्णित के रूप में अगर
यह वास्तव में पर निर्भर करता है है जिस तरह से संकलक इसे संभालता है। मुझे नहीं लगता कि इस व्यवहार का सुझाव देने वाला कोई आधिकारिक पत्र है। – iqstatic
उच्च प्रदर्शन के लिए आपके 'लिंक' में कारण' एडीडी 'और' असाइनमेंट 'के दो चरण शामिल हैं। हां, 'असाइनमेंट' समय खपत हो सकता है लेकिन इस मामले में इससे कोई फर्क नहीं पड़ता क्योंकि 'i + 1' के साथ आवंटित चर को पहले से ही रजिस्टर में उपलब्ध है।तो, ['आवंटन लिखें '] (http://www.cs.iastate.edu/~prabhu/Tutorial/CACHE/interac.html) का परिणाम प्रदर्शन क्षति नहीं होता है। – DOOM
मुझे लगता है कि अधिकांश कंपाइलर्स उन्हें समान बनाने के लिए अनुकूलित करेंगे, लेकिन कुछ निर्देश सेट में, वृद्धि परमाणु है लेकिन असाइनमेंट और अतिरिक्त में दो कॉल लगते हैं। – Novaterata