c++ - सी++ में एक सूचक, स्केलर और संदर्भ कब वापस करें?




pointers reference (4)

मैं जावा से सी ++ में जा रहा हूं और भाषा की लचीलापन में थोड़ा उलझन में हूं। एक बिंदु यह है कि वस्तुओं को स्टोर करने के तीन तरीके हैं: एक सूचक, एक संदर्भ और एक स्केलर (यदि मैं इसे सही ढंग से समझता हूं तो ऑब्जेक्ट को स्वयं संग्रहित करता है)।

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

MyType &MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

यह संकलित नहीं होता है, क्योंकि t केवल getSomeAttribute() के दायरे में मौजूद है और यदि मैं इसका संदर्भ देता हूं, तो क्लाइंट इसका उपयोग करने से पहले कहीं भी इंगित नहीं करेगा।

इसलिए मुझे दो विकल्पों के साथ छोड़ दिया गया है:

  1. एक सूचक वापस करें
  2. एक स्केलर लौटें

एक सूचक वापस लौटना इस तरह दिखेगा:

MyType *MyClass::getSomeAttribute() {
    MyType *t = new MyType;
    return t;
}

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

विकल्प ऑब्जेक्ट खुद को वापस करना होगा (स्केलर):

MyType MyClass::getSomeAttribute() {
    MyType t;
    return t;
}

यह बहुत सरल है और मैं इस मामले में जो चाहता हूं: यह एक संदर्भ की तरह लगता है और यह शून्य नहीं हो सकता है। यदि ऑब्जेक्ट क्लाइंट के कोड में दायरे से बाहर है, तो इसे हटा दिया जाता है। बहुत आसान हालांकि, मैं शायद ही कभी ऐसा कर रहा हूं, क्या इसका कोई कारण है? अगर कोई सूचक या संदर्भ के बजाय एक स्केलर लौटाता है तो क्या कोई प्रदर्शन समस्या है?

इस समस्या को संभालने के लिए सबसे आम / सुरुचिपूर्ण दृष्टिकोण क्या है?

https://code.i-harness.com


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


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

संदर्भों के बारे में एक बिंदु:
एक संदर्भ हमेशा एक सूचक नहीं होता है, उदाहरण के लिए जब आपके पास फ़ंक्शन के बॉडी में निम्न कोड होता है, तो संदर्भ एक सूचक नहीं होता है:

int adad=5;
int & reference=adad;  

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

संदर्भ द्वारा वापसी के संबंध में एक बिंदु:
इनलाइन फ़ंक्शंस और ऑप्टिमाइज़ेशन के मामले में, संदर्भ द्वारा लौटने में पते लेने या सूचक शामिल नहीं होंगे।


मूल्य से लौटने से प्रदर्शन दंड का परिचय मिल सकता है क्योंकि इसका मतलब है कि ऑब्जेक्ट की प्रतिलिपि बनाई जानी चाहिए। यदि यह एक बड़ी वस्तु है, एक सूची की तरह, यह ऑपरेशन बहुत महंगा हो सकता है।

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

व्यक्तिगत रूप से, जब मैं किसी सदस्य चर को वापस कर रहा हूं, तो मैं (आमतौर पर कॉन्स) संदर्भ से लौटता हूं, और किसी प्रकार की स्मार्ट पॉइंटर ऑब्जेक्ट (अक्सर ::std::auto_ptr ) ::std::auto_ptr हूं जब मुझे गतिशील रूप से कुछ आवंटित करने की आवश्यकता होती है। अन्यथा मैं मूल्य से वापस आती हूं।

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

मुझे लगता है कि जावा से एक बड़ा बदलाव यह है कि const महत्वपूर्ण है और अक्सर उपयोग किया जाता है। इसे समझना और इसे अपने दोस्त बनाना सीखें।

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


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

मुझे लगता है कि आप शायद ही कभी लोगों को ऐसा क्यों देखते हैं क्योंकि आप गलत सी ++ कोड देख रहे हैं। ;) जावा से आने वाले अधिकांश लोग इस तरह कुछ करने में असहज महसूस करते हैं, इसलिए वे जगह पर new कॉल करते हैं। और फिर उन्हें जगह पर मेमोरी लीक मिलती है, उन्हें नल और अन्य सभी समस्याओं का कारण बनना पड़ता है। :)

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





scalar