क्या 'उत्परिवर्तित' कीवर्ड का कोई उद्देश्य है जो चर को एक कांस्ट फ़ंक्शन द्वारा संशोधित करने की अनुमति देता है?


527

कुछ समय पहले मैं कुछ कोड भर आया था जो mutableकीवर्ड के साथ एक वर्ग के सदस्य चर को चिह्नित करता था। जहाँ तक मैं देख सकता हूँ यह आपको एक चर को संशोधित करने की अनुमति देता है const:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

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


2
एक सवाल हालांकि, अगर आप कुछ भी संशोधित नहीं कर रहे हैं, तो आपको पहले स्थान पर म्यूटेक्स का उपयोग करने की आवश्यकता क्यों है? मैं बस इसे समझना चाहता हूं।
Misgevolution

@Misgevolution आप कुछ संशोधित कर रहे हैं, आप बस नियंत्रित कर रहे हैं कि कौन / कैसे कांस्टेबल के माध्यम से संशोधन कर सकता है। एक बहुत ही अच्छा उदाहरण है, कल्पना करें कि अगर मैं केवल दोस्तों को नॉन-कॉस्ट हैंडल देता हूं, तो दुश्मनों को एक कॉस्ट हैंडल मिलता है। मित्र संशोधित कर सकते हैं, दुश्मन नहीं कर सकते।
इहानी

1
नोट: यहां कीवर्ड का उपयोग करने का एक बड़ा उदाहरण है mutable: stackoverflow.com/questions/15999123/…
गेब्रियल स्टेपल्स

मैं चाहता हूं कि इसका इस्तेमाल const(प्रकारों) को ओवरराइड करने के लिए किया जा सकता है, इसलिए मुझे ऐसा करने की ज़रूरत नहीं है: class A_mutable{}; using A = A_mutable const; mutable_t<A> a;अगर मुझे कॉन्स्टिट-बाय-डिफॉल्ट, यानी mutable A a;(स्पष्ट म्यूटेबल) और A a;(निहित कॉन्स्टेंस) चाहिए।
alfC

जवाबों:


351

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

चूँकि c ++ 11 mutableका उपयोग लैम्बडा पर किया जा सकता है ताकि यह निरूपित किया जा सके कि मूल्य द्वारा पकड़ी गई चीजें परिवर्तनीय हैं (वे डिफ़ॉल्ट रूप से नहीं हैं):

int x = 0;
auto f1 = [=]() mutable {x = 42;};  // OK
auto f2 = [=]()         {x = 42;};  // Error: a by-value capture cannot be modified in a non-mutable lambda

52
'उत्परिवर्तित' बिटवाइज़ / लॉजिकल कॉन्स्टेंस को बिल्कुल भी प्रभावित नहीं करता है। C ++ केवल बिटवाइज़ कॉस्ट है और सदस्यों को इस चेकिंग से बाहर करने के लिए 'mutable' कीवर्ड का उपयोग किया जा सकता है। अमूर्त (उदाहरण के लिए। SmartPtrs) के अलावा C ++ में 'लॉजिकल' कास्ट हासिल करना संभव नहीं है।
रिचर्ड कॉर्डन

111
@ रिचर्ड: आप बिंदु को याद कर रहे हैं। कोई "तार्किक कॉन्स्टेबल" कीवर्ड नहीं है, यह सच है, बल्कि, यह एक वैचारिक भेदभाव है जिसे प्रोग्रामर यह तय करने के लिए करता है कि सदस्यों को किस प्रकार के परस्पर क्रिया से बाहर रखा जाना चाहिए, यह इस बात की समझ के आधार पर है कि ऑब्जेक्ट की तार्किक अवलोकन स्थिति का गठन क्या होता है।
टोनी डेलारॉय

6
@ajay हाँ, यह मार्किग के पूरे बिंदु को एक परिवर्तनशील के रूप में एक सदस्य चर के रूप में, इसे कांस्टेबल ऑब्जेक्ट्स में बदलने की अनुमति देता है।
कीथब

6
लैंबडास पर एक-दूसरे की आवश्यकता क्यों है? क्या संदर्भ द्वारा चर पर कब्जा करना पर्याप्त नहीं होगा?
जियोर्जियो

11
@ जियोर्जियो: अंतर यह है कि xलैम्ब्डा के भीतर संशोधित लैम्बडा के भीतर रहता है, यानी लैम्बडा फ़ंक्शन केवल अपनी स्वयं की कॉपी को संशोधित कर सकता है x। परिवर्तन बाहर दिखाई नहीं देता है, मूल xअभी भी अपरिवर्तित है। इस बात पर विचार करें कि लंबोदर को फनकार वर्ग के रूप में लागू किया जाता है; पकड़े गए चर सदस्य चर के अनुरूप हैं।
सेबेस्टियन मच

138

mutableकीवर्ड बेध लिए एक रास्ता है constघूंघट आप अपने वस्तुओं पर कपड़ा। यदि आप एक स्थिरांक संदर्भ या किसी वस्तु के लिए सूचक है, तो आप किसी भी तरह से उस वस्तु संशोधित नहीं कर सकते छोड़कर कब और कैसे यह चिह्नित है mutable

आपके constसंदर्भ या सूचक के साथ आप इसके लिए विवश हैं:

  • किसी भी दृश्यमान डेटा सदस्यों के लिए केवल एक्सेस पढ़ें
  • केवल उन्हीं विधियों को कॉल करने की अनुमति है जिन्हें चिह्नित किया गया है const

mutableअपवाद यह बनाता है इसलिए अब आप लिख सकते हैं या सेट डेटा सदस्यों को बताया कि चिह्नित कर रहे हैं कर सकते हैंmutable । यह केवल बाहरी रूप से दिखाई देने वाला अंतर है।

आंतरिक रूप से वे constविधियां जो आपको दिखाई देती हैं, वे उन डेटा सदस्यों को भी लिख सकती हैं जो चिह्नित हैं mutable। अनिवार्य रूप से कॉस्ट घूंघट को बड़े पैमाने पर छेद दिया जाता है। यह पूरी तरह से एपीआई डिजाइनर पर निर्भर है कि mutableयह constअवधारणा को नष्ट नहीं करता है और केवल उपयोगी विशेष मामलों में उपयोग किया जाता है। mutableकीवर्ड क्योंकि यह स्पष्ट रूप से निशान डेटा सदस्यों को बताया कि इन विशेष मामलों के अधीन हैं मदद करता है।

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

mutableकीवर्ड के बिना आपको अंततः const_castविभिन्न उपयोगी विशेष मामलों को संभालने के लिए उपयोग करने के लिए मजबूर किया जाएगा (कैशिंग, रिफ गिनती, डीबग डेटा, आदि)। दुर्भाग्य const_castसे काफी अधिक विनाशकारी है mutableक्योंकि यह एपीआई क्लाइंट को constउन वस्तुओं के संरक्षण को नष्ट करने के लिए मजबूर करता है जिसका वह उपयोग कर रहा है। इसके अतिरिक्त यह व्यापक constविनाश का कारण बनता है : const_castएक कॉन्स्टेंट पॉइंटर या संदर्भ आईएनजी अनफिल्टर्ड राइट और मेथड एक्सेस की अनुमति देता है। इसके विपरीत mutableAPI डिज़ाइनर को constअपवादों पर बारीक नियंत्रण रखने के लिए डिज़ाइनर की आवश्यकता होती है, और आमतौर पर ये अपवाद constनिजी डेटा पर काम करने वाले तरीकों में छिपे होते हैं ।

(एनबी मैं डेटा और विधि दृश्यता को कुछ समय के लिए संदर्भित करता हूं। मैं सार्वजनिक बनाम निजी या संरक्षित के रूप में चिह्नित सदस्यों के बारे में बात कर रहा हूं, जो यहां चर्चा की गई एक पूरी तरह से वस्तु सुरक्षा है ।)


8
इसके अलावा, const_castएक constवस्तु के एक हिस्से को संशोधित करने के लिए अपरिभाषित व्यवहार प्राप्त करता है।
ब्रायन

मैं इससे सहमत नहीं हूं क्योंकि यह API क्लाइंट को ऑब्जेक्ट्स की कास्ट प्रोटेक्शन को नष्ट करने के लिए मजबूर करता है । आप उपयोग कर रहे थे const_castएक में सदस्य चर के उत्परिवर्तन लागू करने के लिए constविधि, आप ग्राहक डाली करने के लिए नहीं पूछा है - आप यह कर होता विधि के भीतर से const_casting this। मूल रूप से यह आपको एक विशिष्ट कॉल साइट पर मनमाने सदस्यों पर कब्ज को दरकिनार करने देता है , जबकि mutableआप सभी कॉल साइटों पर एक विशिष्ट सदस्य पर कब्ज को हटाते हैं। उत्तरार्द्ध आमतौर पर वही होता है जो आप विशिष्ट उपयोग (कैशिंग, आंकड़े) के लिए चाहते हैं, लेकिन कभी-कभी const_cast पैटर्न को फिट करता है।
BeeOnRope

1
const_castपैटर्न फिट जैसे जब आप अस्थायी रूप से एक सदस्य को संशोधित करना चाहते, जैसा कि कुछ मामलों में बेहतर है, तो यह बहाल (काफी की तरह boost::mutex)। विधि तार्किक रूप से अंतिम स्थिति के बाद से ही प्रारंभिक है, लेकिन आप उस क्षणिक परिवर्तन करना चाहते हैं। const_castवहाँ उपयोगी हो सकता है क्योंकि यह आपको कास्ट को विशेष रूप से उस विधि में कास्ट करने की सुविधा देता है जिससे आप उत्परिवर्तन पूर्ववत हो जाएंगे, लेकिन mutableयह उचित नहीं होगा क्योंकि यह सभी तरीकों से कास्ट सुरक्षा को हटा देगा , जो जरूरी नहीं कि सभी "का पालन करें" , पूर्ववत करें।
BeeOnRope

2
स्थिरांक के संभावित प्लेसमेंट परिभाषित केवल पढ़ने के लिए स्मृति में वस्तु (अधिक आम तौर पर, स्मृति के रूप में चिह्नित केवल पढ़ने के लिए) और संबद्ध मानक भाषा है कि अनुमति देता है इस बनाता है const_castएक कम समय बम हालांकि। mutableऐसी कोई समस्या नहीं है क्योंकि ऐसी वस्तुओं को केवल-पढ़ने के लिए मेमोरी में नहीं रखा जा सकता है।
मधुमक्खी पालन

75

बढ़ावा देने के साथ आपका उपयोग :: mutex वास्तव में इस कीवर्ड के लिए क्या है। एक अन्य उपयोग आंतरिक परिणाम कैशिंग के लिए गति तक पहुँचने के लिए है।

मूल रूप से, 'उत्परिवर्तित' किसी भी वर्ग विशेषता पर लागू होता है जो वस्तु के बाहरी रूप से दृश्यमान स्थिति को प्रभावित नहीं करता है।

आपके प्रश्न में नमूना कोड में, उत्परिवर्तनीय अनुचित हो सकता है यदि बाहरी अवस्था में do_ का मूल्य प्रभावित होता है, यह इस पर निर्भर करता है कि क्या है ...; अंश।


35

म्यूटेबल विशिष्ट विशेषता के रूप में चिह्नित करने के लिए है constतरीकों के भीतर से परिवर्तनीय । यही इसका एकमात्र उद्देश्य है। उपयोग करने से पहले ध्यान से सोचें, क्योंकि यदि आप उपयोग के बजाय डिज़ाइन बदलते हैं तो आपका कोड संभवतः क्लीनर और अधिक पठनीय होगा mutable

http://www.highprogrammer.com/alan/rants/mutable.html

तो अगर उपरोक्त पागलपन नहीं है तो क्या है, यह किस लिए है? यहां सूक्ष्म मामला है: उत्परिवर्तित उस मामले के लिए है जहां एक वस्तु तार्किक रूप से स्थिर है, लेकिन व्यवहार में परिवर्तन की आवश्यकता है। ये मामले कम और दूर के हैं, लेकिन वे मौजूद हैं।

लेखक द्वारा दिए गए उदाहरणों में कैशिंग और अस्थायी डीबगिंग चर शामिल हैं।


2
मुझे लगता है कि यह लिंक एक ऐसे परिदृश्य का सबसे अच्छा उदाहरण देता है जहाँ उत्परिवर्ती मददगार है। यह लगभग प्रतीत होता है कि वे विशेष रूप से डीबगिंग के लिए उपयोग किए जाते हैं। (प्रति सही उपयोग)
उत्साही

mutableकोड का उपयोग अधिक पठनीय और क्लीनर बना सकता है। निम्नलिखित उदाहरण में, उम्मीद के मुताबिक किया readजा सकता constहै। `उत्परिवर्ती m_mutex; कंटेनर m_container; शून्य जोड़ (आइटम आइटम) {लॉकगार्ड लॉक (m_mutex); m_container.pushback (आइटम); } आइटम पढ़ा () कॉन्स्ट {लॉकगार्ड लॉक (m_mutex); वापसी m_container.first (); } `
गु। थिलेमन

एक बेहद लोकप्रिय उपयोग मामला है: रेफरी मायने रखता है।
सेवा अलेक्सेयेव

33

यह उन स्थितियों में उपयोगी है जहां आपने आंतरिक स्थिति जैसे कि कैश को छिपाया है। उदाहरण के लिए:

वर्ग हैशटेबल
{
...
जनता:
    स्ट्रिंग लुकअप (स्ट्रिंग कुंजी) कास्ट
    {
        अगर (कुंजी == lastKey)
            अंतिम वापसी;

        स्ट्रिंग मान = लुकअपइंटरनल (की);

        lastKey = कुंजी;
        lastValue = मूल्य;

        प्रतिलाभ की मात्रा;
    }

निजी:
    mutable string lastKey, lastValue;
};

और फिर आपके पास एक const HashTableवस्तु हो सकती है फिर भी इसकी lookup()विधि का उपयोग करें , जो आंतरिक कैश को संशोधित करता है।


9

mutable जब आप किसी अन्यथा स्थिर फ़ंक्शन में डेटा को संशोधित करने की अनुमति देने का अनुमान लगाते हैं, तो आप मौजूद होते हैं।

आशय यह है कि आपके पास एक फ़ंक्शन हो सकता है जो ऑब्जेक्ट की आंतरिक स्थिति में "कुछ भी नहीं करता है", और इसलिए आप फ़ंक्शन को चिह्नित करते हैं const, लेकिन आपको वास्तव में कुछ वस्तुओं की स्थिति को संशोधित करने की आवश्यकता हो सकती है जो इसके सही को प्रभावित नहीं करती हैं कार्यक्षमता।

कीवर्ड संकलक के संकेत के रूप में कार्य कर सकता है - एक सैद्धांतिक संकलक एक स्थिर वस्तु (जैसे एक वैश्विक) को स्मृति में रख सकता है जिसे केवल पढ़ने के लिए चिह्नित किया गया था। mutableसंकेत की उपस्थिति कि यह नहीं किया जाना चाहिए।

यहां पर परिवर्तन योग्य डेटा घोषित करने और उपयोग करने के कुछ मान्य कारण दिए गए हैं:

  • धागा सुरक्षा। घोषणा mutable boost::mutexकरना पूरी तरह से उचित है।
  • सांख्यिकी। किसी फ़ंक्शन को कॉल की संख्या की गणना करना, इसके कुछ या सभी तर्क दिए गए हैं।
  • Memoization। कुछ महंगे उत्तर की गणना करना, और फिर इसे फिर से पुन: प्रकाशित करने के बजाय भविष्य के संदर्भ के लिए संग्रहीत करना।

2
अच्छा जवाब, म्यूटेबल होने के बारे में टिप्पणी के अलावा एक "संकेत" है। इससे ऐसा लगता है कि यदि संकलक ने ऑब्जेक्ट को रोम में रखा तो उत्परिवर्तित सदस्य कभी-कभी उत्परिवर्तित नहीं होगा। उत्परिवर्तनीय के व्यवहार को अच्छी तरह से परिभाषित किया गया है।
रिचर्ड कॉर्डन

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

@HagenvonEitzen - मुझे पूरा यकीन है कि यह गलत है। जब तक यह साबित नहीं हो सकता कि कोई साइड इफेक्ट नहीं है तब तक एक कंपाइलर लूप से बाहर नहीं निकल सकता। यही कारण है कि सबूत आम तौर पर वास्तव में समारोह (अक्सर के बाद यह inlined जाता है) और पर भरोसा नहीं के कार्यान्वयन का निरीक्षण शामिल है const(और इस तरह एक निरीक्षण सफल या पर ध्यान दिए बिना असफल हो जायेगी constया mutable)। बस फ़ंक्शन की घोषणा करना constपर्याप्त नहीं है: एक constफ़ंक्शन साइड इफेक्ट के लिए स्वतंत्र है जैसे कि एक वैश्विक चर को संशोधित करना या फ़ंक्शन के लिए कुछ पारित किया गया है, इसलिए यह उस प्रमाण के लिए उपयोगी गारंटी नहीं है।
BeeOnRope

अब, कुछ संकलक के पास विशेष एक्सटेंशन हैं जैसे कि gcc का _attribute __ ((const)) और __attribute __ ((शुद्ध)), जिसमें _do के ऐसे प्रभाव हैं , लेकिन यह केवल constC ++ में कीवर्ड से संबंधित है ।
BeeOnRope

8

ठीक है, हाँ, यह वही करता है। मैं इसका उपयोग उन सदस्यों के लिए करता हूं जो ऐसे तरीकों से संशोधित होते हैं जो तार्किक रूप से एक वर्ग की स्थिति को नहीं बदलते हैं - उदाहरण के लिए, कैश को लागू करके लुकअप को गति देने के लिए:

class CIniWrapper
{
public:
   CIniWrapper(LPCTSTR szIniFile);

   // non-const: logically modifies the state of the object
   void SetValue(LPCTSTR szName, LPCTSTR szValue);

   // const: does not logically change the object
   LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const;

   // ...

private:
   // cache, avoids going to disk when a named value is retrieved multiple times
   // does not logically change the public interface, so declared mutable
   // so that it can be used by the const GetValue() method
   mutable std::map<string, string> m_mapNameToValue;
};

अब, आपको इसका उपयोग सावधानी से करना चाहिए - संगामिति समस्या एक बड़ी चिंता है, क्योंकि एक कॉलर यह मान सकता है कि यदि वे केवल constविधियों का उपयोग कर रहे हैं तो वे थ्रेड सुरक्षित हैं । और निश्चित रूप से, mutableडेटा को संशोधित करने से किसी भी महत्वपूर्ण फैशन में वस्तु के व्यवहार में बदलाव नहीं होना चाहिए, कुछ ऐसा जो उदाहरण के द्वारा दिए गए उल्लंघन का हो सकता है अगर, उदाहरण के लिए, यह उम्मीद की गई थी कि डिस्क पर लिखे गए परिवर्तन तुरंत ऐप को दिखाई देंगे। ।


6

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

उत्परिवर्तित निर्दिष्ट कंपाइलर और रीडर दोनों को सूचित करता है कि यह सुरक्षित है और उम्मीद है कि एक सदस्य चर को एक कास्ट सदस्य फ़ंक्शन के भीतर संशोधित किया जा सकता है।


4

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


4

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


3

जब उन चीजों के लिए "उत्परिवर्तित" का उपयोग करें, जो उपयोगकर्ता के लिए तार्किक रूप से स्टेटलेस हैं (और इस प्रकार सार्वजनिक कक्षा 'एपीआई' में "कास्ट" गेटर्स होना चाहिए) लेकिन अंतर्निहित प्रभाव (आपके कोड में कोड) में स्टेटलेस नहीं हैं।

जिन मामलों में मैं इसका सबसे अधिक उपयोग करता हूं, वे राज्य-कम "सादे पुराने डेटा" सदस्यों के आलसी प्रारंभिककरण हैं। अर्थात्, यह संकीर्ण मामलों में आदर्श है जब ऐसे सदस्य (प्रोसेसर) या तो (मेमोरी) बनाने के लिए महंगे होते हैं या ऑब्जेक्ट के कई उपयोगकर्ता कभी भी उनके लिए नहीं पूछेंगे। उस स्थिति में आप प्रदर्शन के लिए अंतिम छोर पर आलसी निर्माण चाहते हैं, क्योंकि निर्मित 90% ऑब्जेक्ट्स को उन्हें बिल्कुल भी बनाने की आवश्यकता नहीं होगी, फिर भी आपको सार्वजनिक उपभोग के लिए सही स्टेटलेस एपीआई प्रस्तुत करने की आवश्यकता है।


2

उत्परिवर्तनीय बिट कांस्टेबल constसे वर्ग के लिए तार्किक कास्ट के अर्थ को बदल देता है ।

इसका मतलब यह है कि उत्परिवर्तित सदस्यों वाली कक्षाएं अब बिटवाइज़ कॉन्स्ट हो गई हैं और अब निष्पादन योग्य के केवल-पढ़ने वाले वर्गों में दिखाई नहीं देंगी।

इसके अलावा, यह constसदस्य कार्यों का उपयोग किए बिना परिवर्तनशील सदस्यों को बदलने की अनुमति देकर टाइप-चेकिंग को संशोधित करता है const_cast

class Logical {
    mutable int var;

public:
    Logical(): var(0) {}
    void set(int x) const { var = x; }
};

class Bitwise {
    int var;

public:
    Bitwise(): var(0) {}
    void set(int x) const {
        const_cast<Bitwise*>(this)->var = x;
    }
};

const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.

int main(void)
{
    logical.set(5); // Well defined.
    bitwise.set(5); // Undefined.
}

अधिक विवरण के लिए अन्य उत्तर देखें, लेकिन मैं यह उजागर करना चाहता था कि यह केवल टाइप-सिट्टी के लिए नहीं है और यह संकलित परिणाम को प्रभावित करता है।


1

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

ऐसा लगता है कि मेरे लिए भी ज्यादातर समय हैक होता है। बहुत कम स्थितियों में उपयोगी।


1

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

सामान्य तौर पर, mutableकीवर्ड का उपयोग करने के विकल्प आमतौर पर विधि या const_castचाल में एक स्थिर चर होते हैं ।

एक और विस्तृत विवरण में है यहाँ है


1
मैंने स्थैतिक सदस्यों को उत्परिवर्तित सदस्यों के सामान्य विकल्प के रूप में उपयोग करने के बारे में कभी नहीं सुना है। और const_castकेवल तब के लिए है जब आप जानते हैं (या गारंटी दी गई है) कि कुछ बदला नहीं जाएगा (उदाहरण के लिए जब सी पुस्तकालयों में हस्तक्षेप किया जाता है) या जब आप जानते हैं कि इसे कब्ज घोषित नहीं किया गया था। यानी, एक अपरिष्कृत व्यवहार में एक कास्ट-कास्टेड कॉन्स्टेबल चर को संशोधित करता है।
सेबेस्टियन मच

1
@phresnel "स्टैटिक वेरिएबल्स" से मेरा मतलब था कि स्टैटिस्टिक ऑटोमैटिक वैरिएबल इन द मेथड (जो कॉल के पार रहता है)। और const_castएक वर्ग के सदस्य को एक constतरीके से संशोधित करने के लिए इस्तेमाल किया जा सकता है , जिसे मैंने उल्लेख किया है ...
डैनियल हर्शकोविच

1
यह मेरे लिए स्पष्ट नहीं था, जैसा कि आपने "सामान्य रूप से" लिखा है :) के माध्यम से संशोधित करने के संबंध में const_cast, जैसा कि कहा गया है कि यह केवल तब अनुमति है जब ऑब्जेक्ट घोषित नहीं किया गया था const। जैसे const Frob f; f.something();, void something() const { const_cast<int&>(m_foo) = 2;अपरिभाषित व्यवहार में परिणाम।
सेबस्टियन मच

1

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


1

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


0

सबसे अच्छे उदाहरणों में से एक जहां हम परस्पर उपयोग करते हैं, वह है गहरी प्रतिलिपि में। कॉपी कंस्ट्रक्टर में हम const &objतर्क के रूप में भेजते हैं। तो बनाई गई नई वस्तु निरंतर प्रकार की होगी। यदि हम बदलना चाहते हैं (ज्यादातर हम नहीं बदलेंगे, तो दुर्लभ स्थिति में हम बदल सकते हैं) इस नए बनाए गए कॉन्स्टेंट ऑब्जेक्ट में सदस्यों को हमें इसे घोषित करने की आवश्यकता हैmutable

mutableभंडारण वर्ग का उपयोग केवल एक वर्ग के गैर स्थैतिक गैर कॉन्स्टेबल डेटा सदस्य पर किया जा सकता है। किसी वर्ग का म्यूटेबल डेटा सदस्य संशोधित किया जा सकता है, भले ही वह उस ऑब्जेक्ट का हिस्सा हो जिसे कॉन्स्टेबल घोषित किया गया हो।

class Test
{
public:
    Test(): x(1), y(1) {};
    mutable int x;
    int y;
};

int main()
{
    const Test object;
    object.x = 123;
    //object.y = 123;
    /* 
    * The above line if uncommented, will create compilation error.
    */   

    cout<< "X:"<< object.x << ", Y:" << object.y;
    return 0;
}

Output:-
X:123, Y:1

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


-1

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

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