संदर्भ बनाम पासिंग वैल्यू से गुजरने में क्या अंतर है?


562

के बीच क्या अंतर है

  1. संदर्भ द्वारा पारित एक पैरामीटर
  2. एक पैरामीटर मूल्य द्वारा पारित?

क्या आप मुझे कुछ उदाहरण दे सकते हैं, कृपया



1
यदि आपको पता नहीं है कि पता या मूल्य क्या है तो यहां
हनी

जवाबों:


1079

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

नई भाषाएं 2 एक ही प्रभाव (नीचे देखें) प्राप्त करने के लिए तकनीकों की एक अलग (लेकिन समान) जोड़ी का उपयोग करती हैं जो भ्रम का प्राथमिक स्रोत है।

भ्रम का एक माध्यमिक स्रोत यह तथ्य है कि "संदर्भ के माध्यम से" में, "संदर्भ" का सामान्य शब्द "संदर्भ" की तुलना में एक संकीर्ण अर्थ है (क्योंकि वाक्यांश इसे पूर्व निर्धारित करता है)।


अब, प्रामाणिक परिभाषा है:

  • जब एक पैरामीटर को संदर्भ द्वारा पास किया जाता है , तो कॉल करने वाला और कैली पैरामीटर के लिए एक ही चर का उपयोग करता है । यदि कैली पैरामीटर पैरामीटर को संशोधित करता है, तो प्रभाव कॉलर के चर को दिखाई देता है।

  • जब कोई पैरामीटर मान द्वारा पारित किया जाता है , तो कॉलर और कैली में एक ही मूल्य के साथ दो स्वतंत्र चर होते हैं। यदि कैली पैरामीटर पैरामीटर को संशोधित करता है, तो कॉल करने वाले के लिए प्रभाव दिखाई नहीं देता है।

इस परिभाषा में ध्यान देने योग्य बातें हैं:

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

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


अब, आधुनिक भाषाओं में, चर "संदर्भ प्रकार" के होते हैं (एक अन्य अवधारणा जो "संदर्भ से गुजरती है" और इसके द्वारा प्रेरित की तुलना में बाद में आविष्कार की गई है), अर्थात वास्तविक वस्तु डेटा कहीं अलग (आमतौर पर, ढेर पर), और इसे केवल "संदर्भ" कभी भी चर में रखा जाता है और मापदंडों के रूप में पारित किया जाता है। 3

इस तरह के संदर्भ को पास करना मूल्य के अंतर्गत आता है क्योंकि एक चर का मूल्य तकनीकी रूप से संदर्भ ही होता है, न कि संदर्भित वस्तु का। हालाँकि, प्रोग्राम का शुद्ध प्रभाव पास-पास-वैल्यू या पास-बाय-रेफरेंस के समान हो सकता है:

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

जैसा कि आप देख सकते हैं, तकनीक की यह जोड़ी लगभग उन लोगों की है जो परिभाषा में हैं, केवल अप्रत्यक्ष के स्तर के साथ: बस "चर" को "संदर्भित ऑब्जेक्ट" के साथ बदलें।

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


नोट : लंबे समय के लिए, यह उत्तर कहता था:

कहो कि मैं आपके साथ एक वेब पेज साझा करना चाहता हूं। यदि मैं आपको URL बताता हूं, तो मैं संदर्भ से गुजर रहा हूं। आप उस URL का उपयोग उसी वेब पेज को देखने के लिए कर सकते हैं जिसे मैं देख सकता हूं। यदि वह पृष्ठ बदला जाता है, तो हम दोनों परिवर्तन देखते हैं। यदि आप URL हटाते हैं, तो आप जो कुछ भी कर रहे हैं, वह उस पृष्ठ पर आपके संदर्भ को नष्ट कर रहा है - आप वास्तविक पृष्ठ को ही नहीं हटा रहे हैं।

यदि मैं पृष्ठ का प्रिंट आउट लेता हूं और आपको प्रिंटआउट देता हूं, तो मैं मूल्य से गुजर रहा हूं। आपका पृष्ठ मूल की डिस्कनेक्ट की गई प्रतिलिपि है। आपको बाद के कोई भी परिवर्तन नहीं दिखाई देंगे, और आपके द्वारा किए गए कोई भी परिवर्तन (जैसे आपके प्रिंटआउट पर स्क्रैबलिंग) मूल पृष्ठ पर दिखाई नहीं देंगे। यदि आप प्रिंटआउट को नष्ट करते हैं, तो आपने वास्तव में ऑब्जेक्ट की अपनी कॉपी को नष्ट कर दिया है - लेकिन मूल वेब पेज बरकरार है।

यह "संदर्भ" के संकीर्ण अर्थ को छोड़कर ज्यादातर सही है - यह अस्थायी और अंतर्निहित दोनों है (इसका कोई मतलब नहीं है, लेकिन स्पष्ट और / या लगातार होना अतिरिक्त विशेषताएं हैं, पास-दर-संदर्भ अर्थ का एक हिस्सा नहीं है , जैसा कि ऊपर बताया गया है)। एक करीबी सादृश्य आपको एक दस्तावेज़ की एक प्रति देगा जो आपको मूल पर काम करने के लिए आमंत्रित कर रहा है।


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

2 बड़ी उम्र के लोग भी इसका समर्थन करते हैं

3 कई आधुनिक भाषाओं में, सभी प्रकार संदर्भ प्रकार हैं। यह दृष्टिकोण 1975 में भाषा CLU द्वारा अग्रणी था और तब से इसे पायथन और रूबी सहित कई अन्य भाषाओं द्वारा अपनाया गया है। और कई और भाषाएँ एक हाइब्रिड दृष्टिकोण का उपयोग करती हैं, जहां कुछ प्रकार "मूल्य प्रकार" हैं और अन्य "संदर्भ प्रकार" हैं - उनमें से सी #, जावा और जावास्क्रिप्ट हैं।

4 प्रति फिटिंग एक पुराने शब्द को पुनर्चक्रण के साथ कुछ भी बुरा नहीं है, लेकिन किसी को किसी भी तरह यह स्पष्ट करना होगा कि प्रत्येक बार किस अर्थ का उपयोग किया जाता है। ऐसा नहीं करना वास्तव में भ्रम पैदा करता है।


मैं व्यक्तिगत रूप से नई तकनीकों के लिए "नया" या "अप्रत्यक्ष" पास-बाय-वैल्यू / पास-बाय-संदर्भ का उपयोग करूंगा ।
ivan_pozdeev

आपके द्वारा प्रदान की गई "प्रामाणिक" परिभाषा लगभग हर परिचयात्मक प्रोग्रामिंग पाठ्यक्रम में दी गई परिभाषा नहीं है। Google जो संदर्भ से गुजरता है और आपको वह उत्तर नहीं मिलेगा। आपके द्वारा प्रदान की जाने वाली प्रामाणिक परिभाषा शब्द के संदर्भ का दुरुपयोग है, जब आप उस परिभाषा का पालन करते हैं, तो आप एक उपनाम का उपयोग कर रहे हैं न कि एक संदर्भ: आपके पास दो चर हैं जो वास्तव में एक ही चर हैं, जो एक उपनाम है और संदर्भ नहीं है। आपकी प्रामाणिक परिभाषा बिना किसी कारण के बड़े पैमाने पर भ्रम का कारण बनती है। केवल संदर्भ द्वारा पास का अर्थ है पासिंग एड्रेस। यह समझ में आता है और इस व्यर्थ भ्रम से बचना चाहिए।
युंगगुन

@YungGun 1) कृपया "लगभग हर परिचयात्मक प्रोग्रामिंग पाठ्यक्रम में दी गई परिभाषा" का लिंक प्रदान करें। यह भी ध्यान दें कि इसका उद्देश्य आज की वास्तविकताओं में स्पष्ट होना है, न कि एक दशक या तीन दशक पहले की वास्तविकताओं में जब कुछ सीएस पाठ्यक्रम लिखा गया था। 2) "पता" का उपयोग परिभाषा में नहीं किया जा सकता है क्योंकि यह संभावित कार्यान्वयन से जानबूझकर सार करता है। उदा। कुछ भाषाओं (फोरट्रान) में संकेत नहीं हैं; वे इस बात में भी भिन्न होते हैं कि क्या वे उपयोगकर्ता को कच्चा पता उजागर करते हैं (VB नहीं); यह भी एक कच्चा स्मृति पता होना जरूरी नहीं है, जो कुछ भी चर को लिंक करने की अनुमति देगा।
ivan_pozdeev

@ivan_podeev कोई लिंक नहीं है क्षमा करें। मैं कहता हूं "लगभग हर परिचयात्मक पाठ्यक्रम" क्योंकि व्यक्तिगत रूप से, मैं कॉलेज गया और प्रोग्रामिंग बूटकैंप भी ले गया जिसने मुझे सिखाया। ये पाठ्यक्रम आधुनिक थे (5 साल पहले से कम)। एक "कच्चा पता" एक "सूचक" का एक पर्याय है ... आप तकनीकी रूप से सही हो सकते हैं (कुछ चेरी उठाया लिंक के अनुसार) लेकिन आप जिस भाषा का उपयोग कर रहे हैं वह अव्यवहारिक और अधिकांश प्रोग्रामर के लिए भ्रमित करने वाला है। यदि आप इस पर मेरा पूरा विचार चाहते हैं तो मैंने एक 3500 शब्द ब्लॉग पोस्ट लिखी है: medium.com/@isaaccway228/…
YungGun

@YungGun "बहुत लंबा, पढ़ा नहीं"। एक नज़र बिल्कुल जवाब में उल्लिखित भ्रमों को दिखाती है। संदर्भ द्वारा पारित कार्यान्वयन के लिए एक सार तकनीक अज्ञेय है। इससे कोई फर्क नहीं पड़ता कि वास्तव में हुड के नीचे क्या है, यह मायने रखता है कि कार्यक्रम पर क्या प्रभाव पड़ता है।
ivan_pozdeev

150

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

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

कोड्स

चूँकि मेरी भाषा C ++ है, मैं इसे यहाँ प्रयोग करूँगा

// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
    p = NULL;
}

// passes an integer
void call_by_value(int p) { // :2
    p = 42;
}

// passes an integer by reference
void call_by_reference(int & p) { // :3
    p = 42;
}

// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
    *p = 10; // changes what p points to ("what p references" in java)
    // only changes the value of the parameter, but *not* of 
    // the argument passed by the caller. thus it's pass-by-value:
    p = NULL;
}

int main() {
    int value = 10;
    int * pointer = &value;

    call_by_value(pointer); // :1
    assert(pointer == &value); // pointer was copied

    call_by_value(value); // :2
    assert(value == 10); // value was copied

    call_by_reference(value); // :3
    assert(value == 42); // value was passed by reference

    call_by_value_special(pointer); // :4
    // pointer was copied but what pointer references was changed.
    assert(value == 10 && pointer == &value);
}

और जावा में एक उदाहरण चोट नहीं करेगा:

class Example {
    int value = 0;

    // similar to :4 case in the c++ example
    static void accept_reference(Example e) { // :1
        e.value++; // will change the referenced object
        e = null; // will only change the parameter
    }

    // similar to the :2 case in the c++ example
    static void accept_primitive(int v) { // :2
        v++; // will only change the parameter
    }        

    public static void main(String... args) {
        int value = 0;
        Example ref = new Example(); // reference

        // note what we pass is the reference, not the object. we can't 
        // pass objects. The reference is copied (pass-by-value).
        accept_reference(ref); // :1
        assert ref != null && ref.value == 1;

        // the primitive int variable is copied
        accept_primitive(value); // :2
        assert value == 0;
    }
}

विकिपीडिया

http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value

http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference

यह आदमी बहुत ज्यादा नाखून लगाता है:

http://javadude.com/articles/passbyvalue.htm


9
डाउनवोट क्यों? अगर कुछ भी गलत है या गलतफहमी की ओर जाता है तो कृपया एक टिप्पणी छोड़ दें।
जोहान्स शबाब - १b

1
मेरा वोट नहीं था, लेकिन एक छोटी सी बात पर (आप जानते हैं, राष्ट्रपति की बहस में जिस तरह से लिया गया था) मैं कहूंगा कि यह एक "रणनीति" से अधिक "रणनीति" है।
harpo

28
पूर्णता के लिए +1। चढ़ाव के बारे में चिंता न करें - लोग अजीब कारणों से करते हैं। कैलकुलेटर के बारे में एक राय सवाल में हर किसी को एक ऐसे व्यक्ति द्वारा नीचा दिखाया गया था जो नहीं सोचता था कि प्रोग्रामर को कैलकुलेटर का उपयोग करना चाहिए! वैसे भी, मुझे लगा कि आपका जवाब बहुत अच्छा था।
मार्क ब्रिटिंघम

1
स्कीट के स्पष्टीकरण के लिंक टूट गए हैं।
मनी ओरिएंटेड प्रोग्रामर

स्कीट के स्पष्टीकरण के लिंक अभी भी टूटे हुए हैं।
Rokit

85

यहाँ कई उत्तर (और विशेष रूप से सबसे अधिक उत्कीर्ण उत्तर) तथ्यात्मक रूप से गलत हैं, क्योंकि वे गलतफहमी करते हैं कि "संदर्भ द्वारा" वास्तव में क्या मतलब है। यहां मामलों को सीधे सेट करने का मेरा प्रयास है।

टी एल; डॉ

सबसे सरल शब्दों में:

  • वैल्यू बाय कॉल का मतलब है कि आप फ़ंक्शन आर्गुमेंट के रूप में वैल्यू पास करते हैं
  • कॉल बाय रेफरेंस का मतलब है कि आप वेरिएबल्स को फ़ंक्शन आर्गुमेंट्स के रूप में पास करते हैं

रूपक शब्दों में:

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

"कॉल बाय वैल्यू" और "कॉल बाय रेफरेंस" का मतलब नहीं है

ध्यान दें कि ये दोनों अवधारणाएँ संदर्भ प्रकारों की अवधारणा से पूरी तरह से स्वतंत्र और ऑर्थोगोनल हैं (जो कि जावा में सभी प्रकार के उपप्रकार हैं Object, और C # सभी classप्रकार में), या C की तरह सूचक प्रकारों की अवधारणा (जो शब्दार्थ के समकक्ष हैं) जावा के "संदर्भ प्रकार", बस अलग वाक्यविन्यास के साथ)।

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

नोट सी ++ "संदर्भ" (जैसे की एक धारणा है कि int&) वह यह है कि नहीं की तरह जावा और सी # के "संदर्भ प्रकार", लेकिन है "संदर्भ द्वारा कॉल" की तरह। जावा और सी # के "संदर्भ प्रकार", और पायथन में सभी प्रकार, सी और सी ++ को "पॉइंटर प्रकार" कहते हैं (जैसे int*)।


ठीक है, यहाँ लंबी और अधिक औपचारिक व्याख्या है।

शब्दावली

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

शुरू करने के लिए, यहाँ एक सी की तरह एक समारोह घोषणा की भाषा में एक उदाहरण है:

void foo(int param) {  // line 1
  param += 1;
}

और यहाँ इस फ़ंक्शन को कॉल करने का एक उदाहरण है:

void bar() {
  int arg = 1;  // line 2
  foo(arg);     // line 3
}

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

  • fooएक फ़ंक्शन 1 पर घोषित किया गया है (जावा सभी फ़ंक्शन विधियों को बनाने पर जोर देता है, लेकिन अवधारणा सामान्यता के नुकसान के बिना समान है; सी और सी ++ घोषणा और परिभाषा के बीच एक अंतर बनाते हैं जो मैं यहां नहीं जाऊंगा)
  • paramएक औपचारिक पैरामीटर है foo, जिसे लाइन 1 पर भी घोषित किया गया है
  • argएक वैरिएबल है , विशेष रूप से फ़ंक्शन का एक स्थानीय वैरिएबलbar , घोषित और पंक्ति 2 पर आरंभ किया गया
  • argलाइन 3 के विशिष्ट आह्वान का एक तर्क भी हैfoo

यहाँ भेद करने के लिए अवधारणाओं के दो बहुत महत्वपूर्ण समूह हैं। पहला मान वैरिएबल बनाम है :

  • एक मान भाषा में एक अभिव्यक्ति का मूल्यांकन करने का परिणाम है । उदाहरण के लिए, barऊपर के फ़ंक्शन में, लाइन के बाद int arg = 1;, अभिव्यक्ति argका मूल्य है 1
  • एक चर मूल्यों के लिए एक कंटेनर है । एक परिवर्तनीय परिवर्तनशील हो सकता है (यह अधिकांश सी-लाइक भाषाओं में डिफ़ॉल्ट है), केवल पढ़ने के लिए (उदाहरण के लिए जावा finalया सी # का उपयोग करके घोषित readonly) या गहराई से अपरिवर्तनीय (जैसे सी ++ का उपयोग करके const)।

भेद करने के लिए अवधारणाओं की अन्य महत्वपूर्ण जोड़ी पैरामीटर बनाम तर्क है :

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

मूल्य से कॉल करें

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

यह ठीक उसी तरह काम करता है जैसे कि किसी भी अन्य प्रकार के चर मानों के साथ आरंभिक होते हैं। उदाहरण के लिए:

int arg = 1;
int another_variable = arg;

यहां argऔर another_variableपूरी तरह से स्वतंत्र चर हैं - उनके मूल्य एक दूसरे से स्वतंत्र रूप से बदल सकते हैं। हालाँकि, जिस बिंदु पर another_variableघोषित किया गया है, यह उसी मूल्य को धारण करने के लिए आरंभिक है जो argधारण करता है - जो है 1

चूंकि वे स्वतंत्र चर हैं, इसलिए परिवर्तन another_variableप्रभावित नहीं करते हैं arg:

int arg = 1;
int another_variable = arg;
another_variable = 2;

assert arg == 1; // true
assert another_variable == 2; // true

यह बिल्कुल हमारे ऊपर argऔर paramहमारे उदाहरण के बीच के संबंध के समान है, जिसे मैं समरूपता के लिए यहां दोहराऊंगा:

void foo(int param) {
  param += 1;
}

void bar() {
  int arg = 1;
  foo(arg);
}

यह बिल्कुल वैसा ही है जैसे हमने कोड इस तरह लिखा हो:

// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here

अर्थात्, मूल्य द्वारा कॉल को परिभाषित करने की विशेषता यह है कि कैली ( fooइस मामले में) मानों को तर्क के रूप में प्राप्त करता है, लेकिन कॉलर के चर ( इस मामले में) से उन मूल्यों के लिए अपने अलग चर हैंbar

ऊपर मेरे रूपक पर जा रहे हैं, अगर मैं barऔर आप foo, जब मैं आपको फोन करता हूं, तो मैं आपको उस पर लिखे मूल्य के साथ कागज का एक टुकड़ा सौंपता हूं । आप कागज के उस टुकड़े को कहते हैं param। वह मूल्य उस मूल्य की एक प्रति है जो मैंने अपनी नोटबुक (मेरे स्थानीय चर) में लिखी है, एक चर जिसे मैं कहता हूं arg

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

संदर्भ से कॉल करें

में संदर्भ द्वारा कॉल , समारोह का औपचारिक पैरामीटर बस कर रहे हैं नए नाम एक ही चर कि तर्क के रूप में फोन करने वाले की आपूर्ति के लिए।

ऊपर हमारे उदाहरण पर वापस जाना, यह इसके बराबर है:

// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here

चूँकि इसके paramलिए सिर्फ एक और नाम है arg- अर्थात, वे एक ही परिवर्तनशील हैं , परिवर्तन paramपरिलक्षित होते हैं arg। यह मौलिक तरीका है जिसमें कॉल द्वारा संदर्भ कॉल मूल्य से भिन्न होता है।

बहुत कम भाषाएँ संदर्भ द्वारा कॉल का समर्थन करती हैं, लेकिन C ++ इसे इस तरह कर सकती है:

void foo(int& param) {
  param += 1;
}

void bar() {
  int arg = 1;
  foo(arg);
}

इस मामले में, paramकेवल उतना ही मूल्य नहीं है arg, यह वास्तव में arg (केवल एक अलग नाम से) है और इसलिए barयह देख सकते हैं कि argवृद्धि हुई है।

ध्यान दें कि यह है नहीं कैसे जावा, जावास्क्रिप्ट, सी, ऑब्जेक्टिव-सी, अजगर, या लगभग किसी भी अन्य लोकप्रिय भाषा आज काम करता है के किसी भी। इसका मतलब यह है कि उन भाषाओं को संदर्भ द्वारा कॉल नहीं किया जाता है, वे मूल्य से कॉल करते हैं।

परिशिष्ट: ऑब्जेक्ट साझाकरण द्वारा कॉल करें

यदि आपके पास मूल्य से कॉल है , लेकिन वास्तविक मूल्य एक संदर्भ प्रकार या सूचक प्रकार है , तो "मूल्य" स्वयं बहुत दिलचस्प नहीं है (जैसे सी में यह केवल एक प्लेटफ़ॉर्म-विशिष्ट आकार का पूर्णांक है) - क्या है दिलचस्प यह है कि मूल्य किस ओर इशारा करता है

तो क्या है कि संदर्भ प्रकार (अर्थात, सूचक) अंक के लिए है परिवर्तनशील तो एक रोचक प्रभाव संभव है: आप उठाई-टू मूल्य संशोधित कर सकते हैं, और फोन करने वाले की ओर इशारा करने के लिए मूल्य है, भले ही फोन करने वाले का पालन नहीं कर सकते हैं परिवर्तन का निरीक्षण कर सकते पॉइंटर में ही बदल जाता है।

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

बारबरा लिस्कॉव, जब उन्होंने सीएलयू प्रोग्रामिंग भाषा (जिसमें ये शब्दार्थ थे) का आविष्कार किया, तो महसूस किया कि मौजूदा शब्द "मूल्य द्वारा कॉल" और "संदर्भ द्वारा कॉल" इस नई भाषा के शब्दार्थ का वर्णन करने के लिए विशेष रूप से उपयोगी नहीं थे। इसलिए उसने एक नया शब्द का आविष्कार किया: ऑब्जेक्ट शेयरिंग द्वारा कॉल

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


समझाया बेहतर: यहाँ भेद करने के लिए अवधारणाओं के दो बहुत महत्वपूर्ण सेट हैं। The first is value versus variable. The other important pair of concepts to distinguish is parameter versus argument:
एसके वेंकट

2
बहुत बढ़िया जवाब। मुझे लगता है कि मैं यह जोड़ूंगा कि किसी भी नए स्टोरेज को संदर्भ द्वारा पास करने की आवश्यकता नहीं है। पैरामीटर नाम मूल भंडारण (मेमोरी) का संदर्भ देता है। धन्यवाद
drlolly

1
सबसे अच्छा जवाब IMO
राफेल Eyng

59

2 शब्दों को समझने से पहले, आपको निम्नलिखित को समझना होगा। हर वस्तु, 2 चीजें हैं जो इसे प्रतिष्ठित कर सकती हैं।

  • इसका मूल्य है।
  • इसका पता है।

तो अगर तुम कहो employee.name = "John"

पता है कि के बारे में 2 बातें हैं कि name। इसका मान जो "John"मेमोरी में उसका स्थान है और कुछ हेक्साडेसिमल संख्या भी है जो शायद इस प्रकार है 0x7fd5d258dd00:।

भाषा की वास्तुकला या आपकी वस्तु के प्रकार (वर्ग, संरचना इत्यादि) के आधार पर , आप "John"या तो स्थानांतरित होंगे या0x7fd5d258dd00

पासिंग "John"को मूल्य से गुजरने के रूप में जाना जाता है। पासिंग 0x7fd5d258dd00को संदर्भ से गुजरने के रूप में जाना जाता है। जो भी इस मेमोरी लोकेशन की ओर इशारा कर रहा है, उसके मूल्य तक पहुंच होगी "John"

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


3
यही कारण है कि मैं देख रहा था, वास्तव में एक अवधारणा के लिए देखना चाहिए न केवल स्पष्टीकरण, अंगूठे ऊपर भाई।
हिसुम उस्मान

जावा हमेशा मान से पास होता है। जावा में वस्तुओं के संदर्भों को पास करना मान से पास माना जाता है। यह आपके कथन "" 0x7fd5d258dd00 पासिंग को संदर्भ से गुजरने के रूप में जाना जाता है। "
चेतन बरसा

53

यहाँ एक उदाहरण है:

#include <iostream>

void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }

int main()
{
    int x = 0;
    by_val(x); std::cout << x << std::endl;  // prints 0
    by_ref(x); std::cout << x << std::endl;  // prints 2

    int y = 0;
    by_ref(y); std::cout << y << std::endl;  // prints 2
    by_val(y); std::cout << y << std::endl;  // prints 2
}

1
मुझे लगता है कि एक समस्या है क्योंकि अंतिम पंक्ति को 2 के बजाय 0 प्रिंट करना चाहिए। कृपया मुझे बताएं कि क्या मुझे कुछ याद आ रहा है।
तैमूर चांगैज़

@TaimoorChangaiz; कौन सी "अंतिम पंक्ति"? वैसे, यदि आप IRC का उपयोग कर सकते हैं, तो कृपया Freenode पर ## प्रोग्रामिंग पर आएं। वहां चीजों को समझाना काफी आसान होगा। मेरा निक "पिओन" है।
पायन

1
@ EduardoLeón by_val (y); std :: cout << y << std :: endl; // प्रिंट्स 2
तैमूर चांगैज

5
@TaimoorChangaiz: यह 2 प्रिंट क्यों नहीं करेगा? yपूर्ववर्ती पंक्ति द्वारा पहले ही 2 पर सेट कर दिया गया है। यह 0 पर वापस क्यों जाएगा?
पियोन

@ EduardoLeón मेरा बुरा। हाँ आप सही है। सुधार के लिए धन्यवाद
तैमूर चांगैज

28

इसे प्राप्त करने का सबसे सरल तरीका एक एक्सेल फाइल है। उदाहरण के लिए मान लें कि आपके पास सेल A1 और B1 में दो संख्याएँ हैं, 5 और 2 तदनुसार, और आप तीसरे सेल में उनका योग खोजना चाहते हैं, आइए A2 कहें। आप इसे दो तरीकों से कर सकते हैं।

  • या तो सेल A2 में उनके मानों को पास करके = इस सेल में 5 + 2 टाइप करके । इस स्थिति में, यदि A1 या B1 कोशिकाओं के मान बदलते हैं, A2 में योग समान रहता है।

  • या टाइप करके सेल A1 के बी 1 और बी 1 सेल के "संदर्भ" पास करके = A1 + B1 । इस स्थिति में, यदि कक्ष A1 या B1 के मान बदल जाते हैं, तो A2 में योग भी बदल जाता है।


यह अन्य सभी उत्तरों में सबसे सरल और सबसे अच्छा उदाहरण है।
अमित रे

18

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


12

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


7

मान से पास करें - फ़ंक्शन चर की प्रतिलिपि बनाता है और प्रतिलिपि के साथ काम करता है (इसलिए यह मूल चर में कुछ भी नहीं बदलता है)

संदर्भ से गुजारें - फ़ंक्शन मूल चर का उपयोग करता है, यदि आप दूसरे फ़ंक्शन में चर बदलते हैं, तो यह मूल चर में भी बदलता है।

उदाहरण (कॉपी और उपयोग / इसे स्वयं आज़माएं और देखें):

#include <iostream>

using namespace std;

void funct1(int a){ //pass-by-value
    a = 6; //now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a){ //pass-by-reference
    a = 7; //now "a" is 7 both in funct2, main and everywhere else it'll be used
}

int main()
{
    int a = 5;

    funct1(a);
    cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 5
    funct2(a);
    cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 7

    return 0;
}

इसे सरल रखें, झांकें। पाठ की दीवारें एक बुरी आदत हो सकती हैं।


यह समझने में वास्तव में मददगार है कि पैरामीटर मान बदला गया था या नहीं, धन्यवाद!
केविन झाओ

5

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

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

सी # चर्चा देखें और यहां उदाहरण लिंक पाठ को देखें


3

उदाहरण:

class Dog 
{ 
public:
    barkAt( const std::string& pOtherDog ); // const reference
    barkAt( std::string pOtherDog ); // value
};

const &आम तौर पर सबसे अच्छा है। आप निर्माण और विनाश का दंड नहीं उठाते। यदि संदर्भ नहीं है, तो आपका इंटरफ़ेस सुझाव दे रहा है कि यह डेटा में पारित कर देगा।


2

संक्षेप में, पास किया गया मूल्य यह क्या है और संदर्भ द्वारा पारित किया गया है, जहां यह है।

यदि आपका मान VAR1 = "हैप्पी गाइ!" है, तो आप केवल "हैप्पी गाइ!" देखेंगे। यदि VAR1 "हैप्पी गैल!" में परिवर्तित हो जाता है, तो आप यह नहीं जान पाएंगे। यदि यह संदर्भ से गुजरता है, और VAR1 बदलता है, तो आप करेंगे।


2

यदि आप किसी फ़ंक्शन में पास होने के बाद मूल चर के मूल्य को बदलना नहीं चाहते हैं, तो फ़ंक्शन का निर्माण " पास बाय वैल्यू " पैरामीटर के साथ किया जाना चाहिए ।

तब फ़ंक्शन का केवल मान होगा, लेकिन चर में पारित पते का नहीं। चर के पते के बिना, फ़ंक्शन के अंदर कोड फ़ंक्शन के बाहर से देखे गए चर मान को बदल नहीं सकता है।

लेकिन अगर आप फ़ंक्शन को चर के मूल्य को बदलने की क्षमता देना चाहते हैं जैसा कि बाहर से देखा गया है, तो आपको संदर्भ द्वारा पास का उपयोग करने की आवश्यकता है । चूंकि मान और पता (संदर्भ) दोनों फ़ंक्शन के अंदर और उपलब्ध हैं।


1

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


0

यहाँ एक उदाहरण दिया गया है जो मान द्वारा पास के बीच के अंतर को दर्शाता है - सूचक मान - संदर्भ :

void swap_by_value(int a, int b){
    int temp;

    temp = a;
    a = b;
    b = temp;
}   
void swap_by_pointer(int *a, int *b){
    int temp;

    temp = *a;
    *a = *b;
    *b = temp;
}    
void swap_by_reference(int &a, int &b){
    int temp;

    temp = a;
    a = b;
    b = temp;
}

int main(void){
    int arg1 = 1, arg2 = 2;

    swap_by_value(arg1, arg2);
    cout << arg1 << " " << arg2 << endl;    //prints 1 2

    swap_by_pointer(&arg1, &arg2);
    cout << arg1 << " " << arg2 << endl;    //prints 2 1

    arg1 = 1;                               //reset values
    arg2 = 2;
    swap_by_reference(arg1, arg2);
    cout << arg1 << " " << arg2 << endl;    //prints 2 1
}

"संदर्भ से गुजरना" विधि में एक महत्वपूर्ण सीमा है । यदि एक पैरामीटर को संदर्भ के रूप में पारित किया जाता है (तो यह & संकेत द्वारा पूर्ववर्ती है) इसके संबंधित वास्तविक पैरामीटर को एक चर होना चाहिए

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

फ़ंक्शन किसी वैरिएबल के अलावा किसी अन्य चीज़ में मान रखने में सक्षम नहीं है। यह एक शाब्दिक के लिए एक नया मूल्य प्रदान नहीं कर सकता है या इसके परिणाम को बदलने के लिए एक अभिव्यक्ति को मजबूर कर सकता है।

पुनश्च: आप सीधे शब्दों में डायलन बीट्टी के उत्तर की जांच कर सकते हैं जो इसे सीधे शब्दों में समझाता है।


आप कहते हैं "यदि एक पैरामीटर घोषित किया जाता है [एक संदर्भ के रूप में] इसके संबंधित वास्तविक पैरामीटर एक चर होना चाहिए", लेकिन यह सामान्य रूप से सच नहीं है। यदि कोई संदर्भ अस्थायी (जैसे किसी फ़ंक्शन का रिटर्न मान) के लिए बाध्य है, तो उसके जीवनकाल को संदर्भ से मेल खाने के लिए बढ़ाया जाता है। देखें यहाँ जानकारी के लिए।
क्रिस हंट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.