2010-11-13 12 views
10

पर विचार करें आप की तरह"डबल" असाइनमेंट - क्या इससे बचा जाना चाहिए?

i = j = 0 

मान इस पसंद का अपनी भाषा में अच्छी तरह से परिभाषित किया गया है कुछ अभिव्यक्ति की है। यह आम तौर पर इस तरह

i = 0 
j = 0 

मैं कभी कभी पुस्तकालय कोड में यह देखने के दो भाव में विभाजित करने के लिए बेहतर होगा। यह प्रजनन के मामले में आपको बहुत अधिक खरीद नहीं लगता है और दो बयानों से बेहतर प्रदर्शन नहीं करना चाहिए (हालांकि यह संकलक निर्भर हो सकता है)। तो, क्या एक दूसरे पर एक का उपयोग करने का कोई कारण है? या यह सिर्फ व्यक्तिगत वरीयता है? मुझे पता है कि यह एक मूर्ख सवाल की तरह लगता है लेकिन यह अब मुझे लंबे समय से परेशान कर रहा है :-)।

उत्तर

3

दो रूप असाइनमेंट पर विभिन्न बिंदुओं को दर्शाते हैं।

पहला मामला असाइनमेंट (कम से कम आंतरिक) को एक ऑपरेटर (एक फ़ंक्शन लौटने वाला फ़ंक्शन) के रूप में कार्य करता है।

दूसरा मामला असाइनमेंट को एक कथन के रूप में मानता है (कुछ करने का आदेश)।

कुछ ऐसे मामले हैं जहां ऑपरेटर के रूप में असाइनमेंट का मुख्य बिंदु होता है, ज्यादातर ब्रेवटी के लिए, या परिणामों की अपेक्षा करने वाले संदर्भों में उपयोग करने के लिए। हालांकि मुझे यह भ्रमित लगता है। कई कारणों से:

  • असाइनमेंट ऑपरेटर मूल रूप से दुष्प्रभाव ऑपरेटर हैं, और आजकल उन्हें कंप्यूटर्स के लिए अनुकूलित करने में समस्या है। सी और सी ++ जैसी भाषाओं में वे कई अपरिभाषित व्यवहार मामलों, या अप्रत्याशित कोड का कारण बनते हैं।
  • यह स्पष्ट नहीं है कि इसे वापस क्या करना चाहिए। असाइनमेंट ऑपरेटर को उस मान को वापस कर देना चाहिए जिसे असाइन किया गया है, या उसे उस स्थान के पते को वापस कर देना चाहिए जिसे इसे संग्रहीत किया गया है। संदर्भ के आधार पर एक या दूसरा उपयोगी हो सकता है।
  • += जैसे समग्र असाइनमेंट के साथ, यह और भी बदतर है। यह स्पष्ट नहीं है कि ऑपरेटर को प्रारंभिक मूल्य, संयुक्त परिणाम, या यहां तक ​​कि वह स्थान भी संग्रहीत किया जाना चाहिए।

किसी कथन के रूप में असाइनमेंट कभी-कभी मध्यवर्ती चर के लिए होता है, लेकिन यह एकमात्र कमी है जिसे मैं देखता हूं। यह स्पष्ट है और कंपाइलर्स जानते हैं कि इस तरह के बयान कुशलतापूर्वक सफलतापूर्वक कैसे अनुकूलित करें।

असल में, मैं ऑपरेटर के रूप में काम जब भी संभव से बचने होगा। प्रस्तुत मामला बहुत आसान है और वास्तव में भ्रमित नहीं है, लेकिन एक सामान्य नियम के रूप में मैं अभी भी पसंद करूंगा।

i = 0 
j = 0 

या

i, j = 0, 0 

भाषाओं का समर्थन करता है कि, समानांतर कार्य के लिए।

1

दूसरा तरीका अधिक पठनीय और स्पष्ट है, मैं इसे पसंद करता हूं।

int i, j; 
बजाय

int i; 
int j; 

अगर वे लगातार जा रहे हैं:

हालांकि मैं "डबल" घोषणा से बचने की कोशिश। खासकर MyVeryLong.AndComplexType

+1

'नहीं उल्लेख करने के लिए चार i, j; 'बनाम चार * मैं, * जे; '। –

+0

@Ignacio: आपके विषय से संबंधित अच्छा पुराना प्रश्न http://stackoverflow.com/questions/377164/whats-your-preferred-pointer-declaration-style-and- क्यों – abatishchev

2

यह भाषा पर निर्भर करता है। अत्यधिक ऑब्जेक्ट-उन्मुख भाषाओं में, एक ही ऑब्जेक्ट में डबल असाइनमेंट परिणाम कई चरों को आवंटित किए जाते हैं, इसलिए एक चर में परिवर्तन दूसरे में दिखाई देते हैं।

$ python -c 'a = b = [] ; a.append(1) ; print b' 
[1] 
+0

ऐसे मामलों में 'बी = []; ए = बी' स्पष्ट वाक्यविन्यास – kriss

+0

@ क्रिस है: लेकिन सवाल उस वाक्यविन्यास के बारे में नहीं पूछ रहा है। –

+0

मैं यह इंगित कर रहा था कि एक पंक्ति संयुक्त असाइनमेंट के बराबर दोनों objets के लिए एक ही स्थिरता असाइनमेंट नहीं था। यह सम्मेलन पर निर्भर करता है कि असाइनमेंट का परिणाम वह मान है जो पहले चर को सौंपा गया था। यह कई लोगों पर एक संभव विकल्प है। असाइनमेंट (जैसे सी ++) पर निहित का समर्थन करने वाली भाषाओं में यह स्पष्ट नहीं है कि अगर कास्ट किया जाता है तो लौटाया जाने वाला मूल्य ऑब्जेक्ट होना चाहिए (मुझे विश्वास है कि यह पहला है, लेकिन मानक संदर्भ दस्तावेज़ में जांचना होगा ज़रूर)। – kriss

2

अधिकांश लोगों को दोनों संभावनाएं समान रूप से पठनीय मिल जाएंगी। इनमें से कुछ लोगों के लिए किसी भी तरह से व्यक्तिगत वरीयता होगी। लेकिन ऐसे लोग हैं जो पहली नज़र में "डबल असाइनमेंट" से भ्रमित हो सकते हैं। मैं व्यक्तिगत रूप से अलग दृष्टिकोण की तरह, bacause

  • यह
  • यह वास्तव में वर्बोज़ डबल संस्करण
  • यह मेरे = ऑपरेटर
के लिए संबद्धता का नियम भूल जाते हैं की अनुमति देता है की तुलना में नहीं है 100% पठनीय है
8

एक समय पर एक प्रदर्शन अंतर था, जो कि इस तरह के असाइनमेंट का उपयोग किया गया था। compilers में i = 0; j = 0; बारी होगा:

load 0 
store [i] 
load 0 
store [j] 

तो तुम i = j = 0 का उपयोग करके एक निर्देश को बचा सकता है के रूप में संकलक में इस बारी होगा:

load 0 
store [j] 
store [i] 

आजकल compilers द्वारा स्वयं अनुकूलन के इस प्रकार कर सकते हैं। साथ ही, वर्तमान सीपीयू एक ही समय में कई निर्देश चलाते हैं, प्रदर्शन को अब निर्देशों की संख्या में मापा जा सकता है। निर्देश जहां एक क्रिया दूसरे के परिणाम पर भरोसा नहीं करती है, समानांतर में चल सकती है, इसलिए प्रत्येक चर के लिए अलग मान का उपयोग करने वाला संस्करण वास्तव में तेज़ हो सकता है।

प्रोग्रामिंग शैली के बारे में, आपको उस तरीके का उपयोग करना चाहिए जो कोड के इरादे को सर्वोत्तम रूप से व्यक्त करता है।

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

3

सबसे पहले, एक अर्थशास्त्रीय स्तर पर, यह निर्भर करता है कि आप यह कहना चाहते हैं कि i और j समान मूल्य हैं, या केवल दोनों के समान मूल्य होता है।

उदाहरण के लिए, यदि i और j इंडेक्स 2 डी सरणी में हैं, तो वे दोनों शून्य से शुरू होते हैं। j = i = 0 शून्य पर i शुरू होता है, और j शुरू होता है जहां i शुरू कर दिया कहते हैं। यदि आप दूसरी पंक्ति में शुरू करना चाहते हैं, तो आप दूसरे कॉलम पर शुरू नहीं करना चाहते हैं, इसलिए मैं उन्हें एक ही कथन में शुरू नहीं करूँगा - पंक्तियों और स्तंभों के सूचकांक शून्य से शुरू होने के लिए स्वतंत्र रूप से होते हैं।

इसके अलावा, भाषाओं में जहां i और j अभिन्न चर के बजाय जटिल वस्तुओं का प्रतिनिधित्व करते हैं, या जहां काम एक अंतर्निहित रूपांतरण का कारण हो सकता है, वे समान नहीं होते हैं: *

#include <iostream> 

class ComplicatedObject 
{ 
public: 
    const ComplicatedObject& operator= (const ComplicatedObject& other) { 
     std::cout << " ComplicatedObject::operator= (const ComplicatedObject&)\n"; 
     return *this; 
    } 
    const ComplicatedObject& operator= (int value) { 
     std::cout << " ComplicatedObject::operator= (int)\n"; 
     return *this; 
    } 

}; 

int main() 
{ 
    { 
     // the functions called are not the same 
     ComplicatedObject i; 
     ComplicatedObject j; 

     std::cout << "j = i = 0:\n"; 
     j = i = 0; 

     std::cout << "i = 0; j = 0:\n"; 
     i = 0; 
     j = 0; 
    } 

    { 
     // the result of the first assignment is 
     // effected by implicit conversion 
     double j; 
     int i; 

     std::cout << "j = i = 0.1:\n"; 
     j = i = 0.1; 

     std::cout << " i == " << i << '\n' 
        << " j == " << j << '\n' 
        ; 

     std::cout << "i = 0.1; j = 0.1:\n"; 
     i = 0.1; 
     j = 0.1; 

     std::cout << " i == " << i << '\n' 
        << " j == " << j << '\n' 
        ; 
    } 

} 
संबंधित मुद्दे