अपरिवर्तनीय और स्थिर के बीच अंतर


28

मैंने अक्सर शब्दों को देखा है immutableऔर constपरस्पर उपयोग किया है। हालाँकि, मेरे (छोटे से) अनुभव से, दोनों 'कॉन्ट्रैक्ट' में बहुत भिन्न होते हैं जो वे कोड में बनाते हैं:

अपरिवर्तनीय अनुबंध बनाता है कि यह ऑब्जेक्ट नहीं बदलेगा, जो भी (जैसे पायथन ट्यूपल्स, जावा स्ट्रिंग्स)।

कॉन्सट कॉन्ट्रैक्ट करता है कि इस चर के दायरे में इसे संशोधित नहीं किया जाएगा (इस अवधि के दौरान इंगित किए गए ऑब्जेक्ट के लिए अन्य धागे क्या कर सकते हैं, इसके बारे में कोई वादा नहीं करता है, जैसे कि सी / सी ++ कीवर्ड)।

स्पष्ट रूप से, दोनों समान नहीं हैं, जब तक कि भाषा एकल-पिरोया (PHP) नहीं है, या दोनों में रैखिक या अनइकुनस टाइपिंग सिस्टम (क्लीन, मर्करी, एटीएस) है।

पहले, क्या इन दो अवधारणाओं के बारे में मेरी समझ सही है?

दूसरा, यदि कोई अंतर है, तो वे लगभग विशेष रूप से परस्पर विनिमय क्यों किया जाता है?


1
constहर भाषा में मौजूद नहीं है, और परिवर्तनशीलता और अपरिवर्तनीयता हर भाषा में मौजूद नहीं है इसलिए इस भाषा को एगोनिस्टिक बनाना लागू नहीं है। यह भाषा विशिष्ट है जहां ये अवधारणाएं लागू होती हैं।

2
संबंधित, अनुशंसित पढ़ने: किंड ऑफ इम्युटेबिलिटी (कुछ सी # उदाहरण, लेकिन काफी हद तक भाषा-अज्ञेयवादी)। कोई एरिक लिपर्ट को पदक देता है।

जवाबों:


14

मैं C ++ से बात करूंगा, जहां यह अंतर सबसे अधिक प्रासंगिक है।

जैसा कि आप सही ढंग से ध्यान दें, अपरिवर्तनीय का मतलब है कि एक वस्तु अपने निर्माण के बाद बिल्कुल भी नहीं बदल सकती है। यह निर्माण निश्चित रूप से रनटाइम पर हो सकता है, अर्थात, एक constवस्तु अनिवार्य रूप से एक संकलन-समय स्थिर नहीं है। C ++ में, एक ऑब्जेक्ट अपरिवर्तनीय है यदि (1) और या तो (2) या (3) मिलते हैं:

  1. इसका कोई भी सदस्य घोषित नहीं है mutableजो constसदस्य कार्यों से उत्परिवर्तित हो

  2. यह घोषित है const

  3. constसदस्य कार्य किसी भी सदस्य को म्यूट const_castकरने के लिए constयोग्यता को हटाने के लिए उपयोग नहीं करते हैं

हालांकि, आप एक्सेस मॉडिफायर पर भी विचार कर सकते हैं: यदि कोई ऑपरेशन आंतरिक रूप से एक उदाहरण को उत्परिवर्तित करता है, लेकिन इसके सार्वजनिक इंटरफ़ेस के माध्यम से देखने योग्य उदाहरण की स्थिति पर कोई प्रभाव नहीं पड़ता है, तो ऑब्जेक्ट "तार्किक रूप से अपरिवर्तनीय" है।

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

constC ++ में एक और फ़ंक्शन भी है: संदर्भ और बिंदुओं को अर्हता प्राप्त करने के लिए। एक constसंदर्भ एक गैर- constवस्तु को संदर्भित कर सकता है । const_castकिसी ऑब्जेक्ट को किसी constसंदर्भ के माध्यम से म्यूट करने के लिए उपयोग करना कानूनी (हालांकि आम तौर पर आवश्यक या उचित नहीं है) , यदि और केवल तभी उस वस्तु को गैर घोषित किया जाता है const:

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

और निश्चित रूप से यह एक constवस्तु को उत्परिवर्तित करने के लिए अपरिभाषित व्यवहार है :

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

जावा के लिए बोलते हुए जहां कीवर्ड "अंतिम" "कॉन्स्ट" का प्रतिनिधित्व करता है, पर विचार करें:

final Person someone = new Person();

इसका मतलब यह है कि someoneकभी भी किसी अन्य व्यक्ति वस्तु को संदर्भित कर सकते हैं। लेकिन, आप अभी भी संदर्भित किए जा रहे व्यक्ति का विवरण बदल सकते हैं। उदाहरण के लिएsomeone.setMonthlySalary(10000);

लेकिन, अगर someoneएक "अपरिवर्तनीय" वस्तु थी, तो निम्न में से कोई एक सत्य होगा: (ए) आपके पास एक विधि नहीं होगी जिसका नाम होगा setMonthlySalary (बी) कॉलिंगUnsupportedOperationException


10

अपरिवर्तनीय वस्तुएं वे हैं जो इसे बनाने के बाद राज्य नहीं बदलती हैं। उदाहरण के लिए;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

इस उदाहरण में myComplexStr ऑब्जेक्ट अपरिवर्तनीय है, लेकिन स्थिर नहीं है क्योंकि यह मूल्य की गणना है। और यह अपरिवर्तनीय है क्योंकि यह एक स्ट्रिंग है और इसकी स्थैतिक लंबाई संपत्ति है और इसे बदल नहीं सकते हैं।

कांस्ट ऑब्जेक्ट्स का उपयोग आमतौर पर कुछ वास्तविक स्थिरांक की पहचान करने के लिए किया जाता है, जिनके मानों को पाई, "यूएसए", "स्टैकऑवरफ्लो डॉट कॉम", पोर्ट नंबर और इतने पर संकलन से पहले जाना जाता है।

इस दृष्टिकोण से कांस्ट अपरिवर्तनीय वस्तुओं से अलग है क्योंकि उनके मूल्यों की गणना कार्यक्रम द्वारा नहीं की जाती है।

लेकिन अगर आप C ++ में "const" कीवर्ड के बारे में बात कर रहे हैं, तो आप कह सकते हैं कि "const" का उपयोग अपरिवर्तनीय वस्तुओं को बनाने के लिए किया जाता है।


1
C ++ में const अपरिवर्तनीय वस्तुओं का निर्माण नहीं करते हैं, यह केवल एक एक्सेस स्तर है।
Klaim

क्या आप बता सकते हैं कि "कॉन्स्ट डबल पाई = 3.14" कैसे अपरिवर्तनीय नहीं है?
मर्ट अक्काया

वैसे यह निर्भर करता है कि यह कहां है। आइए हम कहते हैं: "डबल * p_pi = const_cast <double *> ((pi); * ppi / 42"; " उदाहरण के लिए। फिर अगर पीआई वैश्विक स्थान या नाम स्थान में है, तो मुझे एक विभाजन दोष मिलता है, लेकिन यह है, मेरा मानना ​​है कि अपरिभाषित व्यवहार, एक विशिष्ट त्रुटि नहीं। यदि pi किसी भी ऑब्जेक्ट का सदस्य है जो रनटाइम पर उपलब्ध है, जो स्थिर नहीं है, तो मुझे pi == 42 मिलता है। आप देख सकते हैं, यहां तक ​​कि उत्परिवर्तित का उपयोग करना भी उपलब्ध है क्योंकि C ++ में कास्ट एक्सेस स्तर, शब्दार्थ के बारे में है, डेटा अपरिवर्तनीयता के बारे में नहीं है, C ++ में प्राप्त करना लगभग असंभव है। आप इसे केवल "अनुकरण" कर सकते हैं। कॉन्स्टेबल अपरिवर्तनीय नहीं है।
Klaim

1
@Kame को एक constतरह से परिवर्तित करना अपरिभाषित व्यवहार है, जहां यह आवंटित नहीं है, IIRC। और अपरिभाषित व्यवहार किसी भी विशिष्ट त्रुटि होने की तुलना में बदतर है। इसका मतलब है कि आप C ++ का उपयोग नहीं करते हैं - C ++ कोई constमान बदलने का कोई साधन प्रदान नहीं करता है ( mutableपाठ्यक्रम के सदस्यों को छोड़कर , लेकिन यह आपकी बात नहीं है), जहाँ तक C ++ का संबंध है, आप ऐसा नहीं कर सकते। अनुमति देने के लिए जो विशिष्ट कार्यान्वयन होता है वह पूरी तरह से एक और मामला है (और मैं आपको शर्त लगाता हूं, यदि आप अनुकूलन के साथ संकलन करते हैं, तो आपके द्वारा खींचा गया स्टंट बाद में अभिव्यक्ति का उपयोग नहीं करेगा piक्योंकि इसे प्रतिस्थापित किया गया है)।

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

8

पहले, क्या इन दो अवधारणाओं के बारे में मेरी समझ सही है?

हां, लेकिन आपका दूसरा प्रश्न बताता है कि आप इन अंतरों को नहीं समझते हैं।

दूसरा, यदि कोई अंतर है, तो वे लगभग विशेष रूप से परस्पर विनिमय क्यों किया जाता है?

constसी ++ में केवल एक्सेस स्तर के लिए उपयोग किया जाता है (इसका अर्थ है "केवल पढ़ने के लिए") , अपरिवर्तनीयता के लिए नहीं। इसका अर्थ है कि पहुँच स्वयं डेटा से पूरी तरह से अलग है। उदाहरण के लिए आप कुछ डेटा में फेरबदल कर सकते हैं, फिर इसे एक कॉन्स्टेक्ट रेफरेंस के माध्यम से उजागर कर सकते हैं। पहुँच केवल पढ़ने के लिए है, लेकिन डेटा ही, जैसा कि सभी डेटाम में परिवर्तनशील है।

कॉन्स्टेंट केवल गैन्ट्री एक्सेस सीमाएँ, जबकि अपरिवर्तनीयता (उदाहरण के लिए डी में) वस्तु के जीवन के किसी भी स्तर पर डेटा को बदलने का वास्तव में कोई तरीका नहीं है

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

अंत में, यह बिल्कुल भी समान नहीं है क्योंकि यह सभी समान गारंटी पर पेश नहीं करता है।


3

जावास्क्रिप्ट की बात, प्रमुख शब्द constऔरObject.freeze

constबाइंडिंगvariables पर लागू होता है । यह एक अपरिवर्तनीय बंधन बनाता है, आप इसके लिए एक नया मान निर्दिष्ट नहीं कर सकते।

Object.freezeऑब्जेक्ट वैल्यू पर काम करता है। यह किसी वस्तु को अपरिवर्तनीय बनाता है । अर्थात्, आप इसके गुणों को नहीं बदल सकते।


0

C ++ में वे समान हैं। यद्यपि आप किसी constऑब्जेक्ट को बदल सकते हैं यदि आपके पास मेमोरी में स्थान है और उस मेमोरी में लिखने के लिए ओएस अनुमति है।


1
वास्तव में यह उनके खिलाफ एक तर्क है : C ++ में केवल कोई अपरिवर्तनीय कीवर्ड या भाषा समर्थन नहीं है। और यह भी, मैं यह मान रहा हूं कि प्रोग्रामर भाषा का उपयोग बड़े पैमाने पर करता है: अन्यथा, कास्ट, भी, का कोई मूल्य नहीं है।
K.Steff

1
@ के। सफ़्फ़ - शायद यह कहना बेहतर होगा कि सी ++ में कोई अतिरिक्त अपरिवर्तनीय-नेस नहीं है, जो कब्ज द्वारा प्रदान किया गया है
मार्टिन बेकेट

बिल्कुल सटीक :)
K.Steff

C ++ में वे समान नहीं हैं। const "रीड-ओनली" एक्सेस स्तर है, इसका मतलब यह नहीं है कि डेटा अपरिवर्तनीय है। आप इसे अधिकतर समय C ++ में बायपास कर सकते हैं।
Klaim

0

C, C ++ और संबंधित भाषाओं में, ऑब्जेक्ट के कॉन्स्टेबल होने और ऑब्जेक्ट के आपके रेफरेंस या पॉइंटर के बीच एक अंतर होता है।

यदि आप एक निरंतर वस्तु को संशोधित करने का प्रयास करते हैं तो आपको अपरिभाषित व्यवहार मिलता है। (आप इसके पते को ले कर उदाहरण के लिए एक निरंतर ऑब्जेक्ट को संशोधित करने का प्रयास कर सकते हैं , पते को गैर-कास्ट पॉइंटर पर कास्टिंग कर सकते हैं, और फिर ऑब्जेक्ट को संशोधित करने के लिए उस गैर-कॉन्स्टेंट पॉइंटर का उपयोग कर सकते हैं)।

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

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

सी में, आपके पास "कॉन्स्ट प्रतिबंधित" सूचक हो सकता है। इसका मतलब है कि इंगित की गई वस्तु अस्थायी रूप से स्थिर है। यदि ऑब्जेक्ट को किसी भी तरह से संशोधित किया गया है, जबकि "कॉन्स्ट प्रतिबंधित" सूचक गुंजाइश में है, तो आपको अपरिभाषित व्यवहार मिलता है। यह एक कास्ट पॉइंटर से अधिक मजबूत है जो केवल इस पॉइंटर के माध्यम से आपको ऑब्जेक्ट बदलने से रोकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.