2016-04-28 10 views
5

मैं निम्नलिखित कोड भर में आया था:सी ++ संदर्भ और वापसी को महत्व देता

class MyClass { 

// various stuff including ... 
    double *myarray; 

    double &operator() (const int n){ 
     return myarray[n]; 
    } 
    double operator() (const int n) const { 
     return myarray[n]; 
    } 

// various other stuff ... 
} 

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

+4

क्या आप सुनिश्चित हैं कि जब आप 'डबल ऑपरेटर() (const int n) देखते हैं, तो आप वास्तव में' डबल ऑपरेटर() (const int n) cont' नहीं देख रहे हैं? – NathanOliver

+0

कुछ शब्दों में: पहला व्यक्ति लेखन का समर्थन करता है; दूसरा ऑब्जेक्ट उपलब्ध है यदि ऑब्जेक्ट स्थिर है। –

+0

संभावित डुप्लिकेट [पॉइंटर वैरिएबल और सी ++ में संदर्भ चर के बीच अंतर क्या हैं?] (Http://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable- और---संदर्भ-चर-इन) – piyushj

उत्तर

6

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

साथ: डबल & ऑपरेटर()

MyClass mm; 
mm(1) = 12; 

लेकिन यह भी:

std::cout << mm(1); 

साथ: डबल ऑपरेटर()

// mm(1) = 12; // this does not compile 
std::cout << mm(1); // this is ok 

भी एक संदर्भ लौटने अधिक आम जब operator[] का उपयोग कर, जब आप std::vector::operator[] का उपयोग की तरह है।

बीटीडब्ल्यू। operator() के दो संस्करण हैं - एक कॉन्स और दूसरा गैर-कॉन्स। कॉन्स ऑब्जेक्ट को कॉन्स्ट ऑब्जेक्ट्स पर कॉल किया जाएगा, जबकि दूसरा कॉन्स्ट ऑब्जेक्ट पर होगा। लेकिन आमतौर पर उनका हस्ताक्षर है:

double& operator() (const int n); 
const double& operator() (const int n) const; 
+0

'मिमी (1) = 12' आह। लाइट चला जाता है धन्यवाद। –

+0

पुन: आपकी अंतिम वाक्य, मूल्य विधि द्वारा पास को 'डबल ऑपरेटर() (कॉन्स int n) const' पढ़ना चाहिए, मैंने संपादन किया था। क्या इससे समस्या हल हो जाती है? –

+0

@ bob.sacamento हाँ, मैंने उत्तर अपडेट किया है – marcinj

4

सामान्यतः, पॉइंटर्स और संदर्भों के बीच का अंतर यह है कि पॉइंटर्स को बदला जा सकता है और nullptr, यानी कुछ भी नहीं इंगित कर सकता है। संदर्भ तय कर रहे हैं।

इस उदाहरण में, हालांकि, ऑपरेटर() संदर्भ को वापस नहीं करता है लेकिन मूल्य की एक प्रति, यानी इस तरह से प्राप्त मूल्य को बदलकर कक्षा में double नहीं बदलता है।

यदि यह वास्तव में एक डबल & लौटाता है, तो आप इन दोनों विधियों को एक दूसरे के साथ (विशेष रूप से उपयोग में विभिन्न टिप्पणियों के साथ) का उपयोग कर सकते हैं, और दोनों की पेशकश केवल इस कक्षा के उपयोगकर्ता के लिए एक स्वागत सुविधा होगी।

4

इसका क्या अर्थ व्यावहारिक रूप से है?

इसका मतलब है कि दूसरी विधि मूल्य-दर-मूल्य देता है, यानी यह सरणी-आइटम/डबल की एक प्रति बनाता है और कॉलर को प्रतिलिपि देता है। पहली विधि संदर्भ द्वारा लौटाती है, यानी यह दोहरी प्रतिलिपि नहीं बनाता है, बल्कि मूल/इन-द-एरे डबल के स्थान का संदर्भ देता है, जिसे कॉलिंग कोड का उपयोग सीधे इन- सरणी डबल, अगर यह चाहता है। (अगर यह मदद करता है, लौटे संदर्भ के अविवेक अर्थ विज्ञान कुछ हद तक सूचक अर्थ विज्ञान की तरह, कर रहे हैं एक वाक्य रचना कि अधिक परंपरागत C/C++ दर-मूल्य कार्यक्षमता के समान है के साथ छोड़कर)

जब मैं एक का उपयोग होता है और मैं दूसरे का उपयोग कब करूंगा?

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

क्या [द्वारा संदर्भ विधि] किसी भी तरह से खतरनाक है?

:, उदाहरण के लिए, यदि आप उस अपरिभाषित व्यवहार का कारण होता है एक स्वत:/ढेर चर के लिए एक संदर्भ, वापस आना था के बाद से चर नष्ट हो जाएगा बुला कोड इसका इस्तेमाल कर सकते से पहले -

यह हो सकता है

double & dont_ever_do_this() 
{ 
    double x = 5.0; // x will be destroyed as this method returns! 
    return x;  // so returning a reference to x is a silly thing to do 
} 

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

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

+0

क्या आप निश्चित हैं * आपके पास इस जवाब में कुछ स्थानों में "पहला" और "दूसरा" मिश्रित नहीं है? – WhozCraig

+0

हा, आप सही हैं। मैं इसे ठीक कर दूंगा। –

2

आप इस लिंक से मूल्य श्रेणियां देख सकते हैं। http://en.cppreference.com/w/cpp/language/value_category

double& operator() में मामला आप lvalue अभिव्यक्ति है और lvalue की तरह उपयोग कर सकते हैं (कार्य के लिए, प्रिंट आदि)

MyClass class; 
class(7) = 21; 

या

std::cout << class(7); 

और double operator() const मामले में आप rvalue अभिव्यक्ति की है। इस मामले में आप इसे const ऑब्जेक्ट के साथ भी उपयोग कर सकते हैं।

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