2008-09-19 13 views
12

मैं समझता हूं कि फ़ंक्शन को ऑब्जेक्ट की स्थिति बदलने की अनुमति नहीं है, लेकिन मैंने सोचा कि मैंने कहीं पढ़ा है कि संकलक को यह मानने की अनुमति थी कि अगर फ़ंक्शन को उसी तर्क के साथ बुलाया गया था, तो यह वही मान वापस करेगा और इस प्रकार यदि उपलब्ध हो तो कैश किए गए मान का पुन: उपयोग कर सकते हैं। जैसेएक कॉन्स्ट सदस्य फ़ंक्शन के अर्थशास्त्र क्या हैं?

class object 
{ 
    int get_value(int n) const 
    { 
     ... 
    } 

... 


object x; 

int a = x.get_value(1); 
    ... 
int b = x.get_value(1); 

तो संकलक दूर दूसरी कॉल का अनुकूलन और या तो एक रजिस्टर में मान का उपयोग या बस b = a;

करना क्या यह सच है हो सकता है?

उत्तर

22

const प्रोग्राम अर्थशास्त्र के बारे में है और कार्यान्वयन विवरण के बारे में नहीं है। जब आप ऑब्जेक्ट की दृश्य स्थिति को नहीं बदलते हैं तो आपको सदस्य फ़ंक्शन const चिह्नित करना चाहिए, और उस ऑब्जेक्ट पर कॉल करने योग्य होना चाहिए जो const है। const कक्षा X पर सदस्य फ़ंक्शन के भीतर, this का प्रकार X const * है: सूचक X ऑब्जेक्ट के लिए सूचक। इस प्रकार सभी सदस्य चर प्रभावी रूप से const उस सदस्य फ़ंक्शन के भीतर प्रभावी होते हैं (mutable को छोड़कर)। यदि आपके पास const ऑब्जेक्ट है, तो आप केवल const सदस्य फ़ंक्शन पर कॉल कर सकते हैं।

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

class X 
{ 
    int data; 
    mutable boost::mutex m; 
public: 
    void set_data(int i) 
    { 
     boost::lock_guard<boost::mutex> lk(m); 
     data=i; 
    } 
    int get_data() const // we want to be able to get the data on a const object 
    { 
     boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const 
     return data; 
    } 
}; 

आप (जैसे std::auto_ptr या boost::shared_ptr के रूप में स्मार्ट संकेत सहित) तो सूचक एक const सदस्य समारोह में const हो जाता है, लेकिन नहीं उठाई-करने के लिए डेटा है, तो आप संशोधित कर सकते हैं तो बजाय सूचक सीधे द्वारा डेटा तक दबाकर रखें बिंदु से डेटा।

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

C++ Standard (C++0x) का अगला संस्करण एक नया कीवर्ड constexpr होगा। constexpr टैग किए गए कार्यों को निरंतर मान लौटाता है, इसलिए परिणाम कैश किए जा सकते हैं। इस तरह के एक समारोह में आप क्या कर सकते हैं इस पर सीमाएं हैं (ताकि संकलक इस तथ्य को सत्यापित कर सकें)।

+0

आह! कॉन्स्टेक्स शायद मैं क्या सोच रहा था! धन्यवाद। – Ferruccio

+0

आपने मेरा दिन बनाया, महोदय। मुझे नहीं पता था कि मुझे हमेशा 'उत्परिवर्तनीय' की ज़रूरत थी। आपका बहुत बहुत धन्यवाद। – lucastamoios

0

मुझे शक है कि यह फ़ंक्शन अभी भी एक वैश्विक कार्य को कॉल कर सकता है जिसने दुनिया की स्थिति को बदल दिया है और न ही उल्लंघन का उल्लंघन नहीं किया है।

2

सदस्य फ़ंक्शन पर कॉन्स कीवर्ड इस पैरामीटर को निरंतर के रूप में चिह्नित करता है। फ़ंक्शन अभी भी वैश्विक डेटा को म्यूट कर सकता है (इसलिए कैश नहीं किया जा सकता है), लेकिन डेटा ऑब्जेक्ट नहीं (कॉन्स्ट ऑब्जेक्ट्स पर कॉल के लिए अनुमति देता है)।

+0

, असल में: - उदाहरण के लिए, निम्नलिखित पूरी तरह से कानूनी (नहीं एक कैश्ड 0 और बार-बार कॉल (बार) बढ़ाने मूल्यों वापस आ जाएगी) है यह। यह मुख्य परिणाम कैशिंग के लिए मुख्य रूप से उपयोगी है। :-) – 0124816

2

इस संदर्भ में, const सदस्य फ़ंक्शन का अर्थ है कि this को const पॉइंटर भी माना जाता है। व्यावहारिक शब्दों में, इसका मतलब है कि की स्थिति को const सदस्य फ़ंक्शन के अंदर संशोधित करने की अनुमति नहीं है।

कोई पक्ष प्रभाव कार्यों के लिए (यानी, क्या आप प्राप्त करना चाहते हैं), जीसीसी एक "समारोह विशेषता" pure कहा जाता है (यदि आप __attribute__((pure)) कह कर इसका इस्तेमाल) है: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

+0

मैं नो-साइड-इफेक्ट फ़ंक्शन प्राप्त करने की कोशिश नहीं कर रहा हूं। मैं सिर्फ फ़ंक्शन कॉन्स बनाने के सभी प्रभावों को समझना चाहता हूं। – Ferruccio

3

सं

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

0

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

2

सदस्य चर पर कीवर्ड mutable ऑब्जेक्ट की स्थिति को बदलने के लिए कॉन्स्ट फ़ंक्शंस को अनुमति देता है। ,

int something() const { return m_pSomeObject->NextValue(); } 

ध्यान दें कि सूचक स्थिरांक हो सकता है, हालांकि:

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

हालांकि, मैं जवाब नहीं दे सकता कि कंपाइलर कॉन्स्ट तरीकों के साथ कैसे काम करता है। मैंने सुना है कि यह कुछ चीजों को अनुकूलित कर सकता है, हालांकि मुझे इसे निश्चित रूप से देखना होगा।

0

कोरी सही है, लेकिन मन में भालू है कि किसी भी सदस्य चर कि चिह्नित कर रहे हैं के रूप में परिवर्तनशील स्थिरांक सदस्य कार्यों में संशोधित किया जा सकता।

इसका यह भी अर्थ है कि इन कार्यों को अन्य कॉन्स फ़ंक्शंस, या अन्य कॉन्स्ट संदर्भों के माध्यम से बुलाया जा सकता है।


संपादित करें: डॉन, 9 सेकंड तक पीटा गया था .... 9 !!! :)

+0

पश्चिम में सबसे तेज गन, ज्यादा? :- पी –

+0

अरे, मेरा जवाब आपके सामने 9 सेकंड से अधिक था। : पी – KTC

0

स्थिर विधियों को स्थिर स्थानीय लोगों को संशोधित करने की भी अनुमति है। यदि आप एक सदस्य लेबल परिवर्तनशील है, तो स्थिरांक समारोह अभी भी संशोधित कर सकते हैं है

class Foo 
{ 
public: 
    int bar() const 
    { 
     static int x = 0; 
     return x++; 
    } 
}; 

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

  • कोई संबंधित समस्या नहीं^_^