के बीच क्या अंतर है
- संदर्भ द्वारा पारित एक पैरामीटर
- एक पैरामीटर मूल्य द्वारा पारित?
क्या आप मुझे कुछ उदाहरण दे सकते हैं, कृपया
के बीच क्या अंतर है
क्या आप मुझे कुछ उदाहरण दे सकते हैं, कृपया
जवाबों:
सबसे पहले और सबसे महत्वपूर्ण है, "सीएस के सिद्धांत में परिभाषित" अंतर के अनुसार "संदर्भ द्वारा पास बनाम अंतर" अब अप्रचलित है क्योंकि तकनीक को मूल रूप से "संदर्भ द्वारा पास" के रूप में परिभाषित किया गया है क्योंकि यह पक्ष से बाहर हो गया है और अब शायद ही कभी इसका उपयोग किया जाता है। 1
नई भाषाएं 2 एक ही प्रभाव (नीचे देखें) प्राप्त करने के लिए तकनीकों की एक अलग (लेकिन समान) जोड़ी का उपयोग करती हैं जो भ्रम का प्राथमिक स्रोत है।
भ्रम का एक माध्यमिक स्रोत यह तथ्य है कि "संदर्भ के माध्यम से" में, "संदर्भ" का सामान्य शब्द "संदर्भ" की तुलना में एक संकीर्ण अर्थ है (क्योंकि वाक्यांश इसे पूर्व निर्धारित करता है)।
अब, प्रामाणिक परिभाषा है:
जब एक पैरामीटर को संदर्भ द्वारा पास किया जाता है , तो कॉल करने वाला और कैली पैरामीटर के लिए एक ही चर का उपयोग करता है । यदि कैली पैरामीटर पैरामीटर को संशोधित करता है, तो प्रभाव कॉलर के चर को दिखाई देता है।
जब कोई पैरामीटर मान द्वारा पारित किया जाता है , तो कॉलर और कैली में एक ही मूल्य के साथ दो स्वतंत्र चर होते हैं। यदि कैली पैरामीटर पैरामीटर को संशोधित करता है, तो कॉल करने वाले के लिए प्रभाव दिखाई नहीं देता है।
इस परिभाषा में ध्यान देने योग्य बातें हैं:
यहाँ "वैरिएबल" का अर्थ है कॉल करने वाला (स्थानीय या वैश्विक) वैरिएबल - यानी यदि मैं संदर्भ से एक स्थानीय वैरिएबल पास करता हूं और इसे असाइन करता हूं, तो मैं कॉलर के वैरिएबल को स्वयं बदल दूंगा, न कि जो कुछ भी यह इंगित करने के लिए इशारा कर रहा है जैसे ।
"संदर्भ" में "संदर्भ" का अर्थ है । सामान्य "संदर्भ" शब्द के साथ अंतर यह है कि यह "संदर्भ" अस्थायी और अंतर्निहित है। मूल रूप से जो कैलेरी मिलती है, वह "वैरिएबल" होती है, जो कि मूल रूप से "वैसी ही" होती है। यह प्रभाव विशेष रूप से कैसे प्राप्त किया जाता है यह अप्रासंगिक है (उदाहरण के लिए भाषा कुछ कार्यान्वयन विवरणों को भी उजागर कर सकती है - पते, संकेत, डेरेफेरेंसिंग - यह सब अप्रासंगिक है; यदि शुद्ध प्रभाव यह है, तो यह पास-बाय-संदर्भ है)।
अब, आधुनिक भाषाओं में, चर "संदर्भ प्रकार" के होते हैं (एक अन्य अवधारणा जो "संदर्भ से गुजरती है" और इसके द्वारा प्रेरित की तुलना में बाद में आविष्कार की गई है), अर्थात वास्तविक वस्तु डेटा कहीं अलग (आमतौर पर, ढेर पर), और इसे केवल "संदर्भ" कभी भी चर में रखा जाता है और मापदंडों के रूप में पारित किया जाता है। 3
इस तरह के संदर्भ को पास करना मूल्य के अंतर्गत आता है क्योंकि एक चर का मूल्य तकनीकी रूप से संदर्भ ही होता है, न कि संदर्भित वस्तु का। हालाँकि, प्रोग्राम का शुद्ध प्रभाव पास-पास-वैल्यू या पास-बाय-रेफरेंस के समान हो सकता है:
जैसा कि आप देख सकते हैं, तकनीक की यह जोड़ी लगभग उन लोगों की है जो परिभाषा में हैं, केवल अप्रत्यक्ष के स्तर के साथ: बस "चर" को "संदर्भित ऑब्जेक्ट" के साथ बदलें।
उनके लिए कोई सहमति-योग्य नाम नहीं है, जो "मूल्य के आधार पर कॉल जहां मूल्य एक संदर्भ है" जैसे विपरीत स्पष्टीकरण की ओर जाता है। 1975 में, बारबरा लिस्कॉव ने " कॉल-बाय-ऑब्जेक्ट-शेयरिंग " (या कभी-कभी "कॉल-बाय-शेयरिंग") शब्द का सुझाव दिया, हालांकि यह कभी भी पकड़ा नहीं गया। इसके अलावा, इन वाक्यांशों में से कोई भी मूल जोड़ी के साथ समानांतर नहीं खींचता है। कोई आश्चर्य नहीं कि पुराने शब्दों का अंत किसी भी चीज़ की अनुपस्थिति में बेहतर तरीके से किया गया, जिससे भ्रम पैदा हुआ। 4
नोट : लंबे समय के लिए, यह उत्तर कहता था:
कहो कि मैं आपके साथ एक वेब पेज साझा करना चाहता हूं। यदि मैं आपको URL बताता हूं, तो मैं संदर्भ से गुजर रहा हूं। आप उस URL का उपयोग उसी वेब पेज को देखने के लिए कर सकते हैं जिसे मैं देख सकता हूं। यदि वह पृष्ठ बदला जाता है, तो हम दोनों परिवर्तन देखते हैं। यदि आप URL हटाते हैं, तो आप जो कुछ भी कर रहे हैं, वह उस पृष्ठ पर आपके संदर्भ को नष्ट कर रहा है - आप वास्तविक पृष्ठ को ही नहीं हटा रहे हैं।
यदि मैं पृष्ठ का प्रिंट आउट लेता हूं और आपको प्रिंटआउट देता हूं, तो मैं मूल्य से गुजर रहा हूं। आपका पृष्ठ मूल की डिस्कनेक्ट की गई प्रतिलिपि है। आपको बाद के कोई भी परिवर्तन नहीं दिखाई देंगे, और आपके द्वारा किए गए कोई भी परिवर्तन (जैसे आपके प्रिंटआउट पर स्क्रैबलिंग) मूल पृष्ठ पर दिखाई नहीं देंगे। यदि आप प्रिंटआउट को नष्ट करते हैं, तो आपने वास्तव में ऑब्जेक्ट की अपनी कॉपी को नष्ट कर दिया है - लेकिन मूल वेब पेज बरकरार है।
यह "संदर्भ" के संकीर्ण अर्थ को छोड़कर ज्यादातर सही है - यह अस्थायी और अंतर्निहित दोनों है (इसका कोई मतलब नहीं है, लेकिन स्पष्ट और / या लगातार होना अतिरिक्त विशेषताएं हैं, पास-दर-संदर्भ अर्थ का एक हिस्सा नहीं है , जैसा कि ऊपर बताया गया है)। एक करीबी सादृश्य आपको एक दस्तावेज़ की एक प्रति देगा जो आपको मूल पर काम करने के लिए आमंत्रित कर रहा है।
1 जब तक आप फोरट्रान या विज़ुअल बेसिक में प्रोग्रामिंग नहीं कर रहे हैं, यह डिफ़ॉल्ट व्यवहार नहीं है, और आधुनिक उपयोग की अधिकांश भाषाओं में, सच्चा कॉल-बाय-संदर्भ भी संभव नहीं है।
2 बड़ी उम्र के लोग भी इसका समर्थन करते हैं
3 कई आधुनिक भाषाओं में, सभी प्रकार संदर्भ प्रकार हैं। यह दृष्टिकोण 1975 में भाषा CLU द्वारा अग्रणी था और तब से इसे पायथन और रूबी सहित कई अन्य भाषाओं द्वारा अपनाया गया है। और कई और भाषाएँ एक हाइब्रिड दृष्टिकोण का उपयोग करती हैं, जहां कुछ प्रकार "मूल्य प्रकार" हैं और अन्य "संदर्भ प्रकार" हैं - उनमें से सी #, जावा और जावास्क्रिप्ट हैं।
4 प्रति फिटिंग एक पुराने शब्द को पुनर्चक्रण के साथ कुछ भी बुरा नहीं है, लेकिन किसी को किसी भी तरह यह स्पष्ट करना होगा कि प्रत्येक बार किस अर्थ का उपयोग किया जाता है। ऐसा नहीं करना वास्तव में भ्रम पैदा करता है।
यह एक तरीका है कि कार्यों के लिए तर्कों को कैसे पारित किया जाए। संदर्भ से गुजरने का मतलब है कि फंक्शंस का पैरामीटर वैसा ही होगा जैसे कॉलर्स की पास की गई दलील (मान नहीं, बल्कि पहचान - चर ही)। मूल्य द्वारा पास का मतलब है कि फंक्शंस का पैरामीटर कॉलर्स के पास किए गए तर्क की एक प्रति होगी। मान समान होगा, लेकिन पहचान - चर - अलग है। इस प्रकार एक फ़ंक्शन में किए गए पैरामीटर को एक मामले में बदल दिया जाता है, जो तर्क में पारित हो जाता है और दूसरे मामले में पैरामीटर को केवल फ़ंक्शन में मान (जो कि केवल एक प्रति है) बदलता है। जल्दी में:
ref
कॉलर और उपयोग किए गए फ़ंक्शन में प्रयुक्त कीवर्ड )। जॉन स्कीट ने भी यहाँ इसकी अच्छी व्याख्या की है ।कोड्स
चूँकि मेरी भाषा 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
यह आदमी बहुत ज्यादा नाखून लगाता है:
यहाँ कई उत्तर (और विशेष रूप से सबसे अधिक उत्कीर्ण उत्तर) तथ्यात्मक रूप से गलत हैं, क्योंकि वे गलतफहमी करते हैं कि "संदर्भ द्वारा" वास्तव में क्या मतलब है। यहां मामलों को सीधे सेट करने का मेरा प्रयास है।
सबसे सरल शब्दों में:
रूपक शब्दों में:
ध्यान दें कि ये दोनों अवधारणाएँ संदर्भ प्रकारों की अवधारणा से पूरी तरह से स्वतंत्र और ऑर्थोगोनल हैं (जो कि जावा में सभी प्रकार के उपप्रकार हैं 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 शब्दों को समझने से पहले, आपको निम्नलिखित को समझना होगा। हर वस्तु, 2 चीजें हैं जो इसे प्रतिष्ठित कर सकती हैं।
तो अगर तुम कहो employee.name = "John"
पता है कि के बारे में 2 बातें हैं कि name
। इसका मान जो "John"
मेमोरी में उसका स्थान है और कुछ हेक्साडेसिमल संख्या भी है जो शायद इस प्रकार है 0x7fd5d258dd00
:।
भाषा की वास्तुकला या आपकी वस्तु के प्रकार (वर्ग, संरचना इत्यादि) के आधार पर , आप "John"
या तो स्थानांतरित होंगे या0x7fd5d258dd00
पासिंग "John"
को मूल्य से गुजरने के रूप में जाना जाता है। पासिंग 0x7fd5d258dd00
को संदर्भ से गुजरने के रूप में जाना जाता है। जो भी इस मेमोरी लोकेशन की ओर इशारा कर रहा है, उसके मूल्य तक पहुंच होगी "John"
।
इसके बारे में अधिक जानकारी के लिए, मैं आपको एक पॉइंटर को डीफ्रेंफर करने के बारे में पढ़ने की सलाह देता हूं और यह भी कि क्लास (संदर्भ) में स्ट्रक्चर (वैल्यू टाइप) का चयन क्यों करें
यहाँ एक उदाहरण है:
#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
}
y
पूर्ववर्ती पंक्ति द्वारा पहले ही 2 पर सेट कर दिया गया है। यह 0 पर वापस क्यों जाएगा?
इसे प्राप्त करने का सबसे सरल तरीका एक एक्सेल फाइल है। उदाहरण के लिए मान लें कि आपके पास सेल A1 और B1 में दो संख्याएँ हैं, 5 और 2 तदनुसार, और आप तीसरे सेल में उनका योग खोजना चाहते हैं, आइए A2 कहें। आप इसे दो तरीकों से कर सकते हैं।
या तो सेल A2 में उनके मानों को पास करके = इस सेल में 5 + 2 टाइप करके । इस स्थिति में, यदि A1 या B1 कोशिकाओं के मान बदलते हैं, A2 में योग समान रहता है।
या टाइप करके सेल A1 के बी 1 और बी 1 सेल के "संदर्भ" पास करके = A1 + B1 । इस स्थिति में, यदि कक्ष A1 या B1 के मान बदल जाते हैं, तो A2 में योग भी बदल जाता है।
मूल्य द्वारा पास आपके द्वारा निर्दिष्ट चर में संग्रहीत डेटा की एक COPY भेजता है, संदर्भ द्वारा पास स्वयं चर के लिए एक सीधा लिंक भेजता है। इसलिए यदि आप किसी चर को संदर्भ द्वारा पास करते हैं और फिर चर को उस खंड के अंदर बदलते हैं जिसे आपने पास किया है, तो मूल चर को बदल दिया जाएगा। यदि आप केवल मूल्य से गुजरते हैं, तो मूल चर उस ब्लॉक से नहीं बदला जा सकेगा जिसे आपने इसे पारित किया था, लेकिन आपको कॉल के समय इसमें जो कुछ भी निहित है उसकी एक प्रति मिल जाएगी।
मान से पास करें - फ़ंक्शन चर की प्रतिलिपि बनाता है और प्रतिलिपि के साथ काम करता है (इसलिए यह मूल चर में कुछ भी नहीं बदलता है)
संदर्भ से गुजारें - फ़ंक्शन मूल चर का उपयोग करता है, यदि आप दूसरे फ़ंक्शन में चर बदलते हैं, तो यह मूल चर में भी बदलता है।
उदाहरण (कॉपी और उपयोग / इसे स्वयं आज़माएं और देखें):
#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;
}
इसे सरल रखें, झांकें। पाठ की दीवारें एक बुरी आदत हो सकती हैं।
उनके बीच एक बड़ा अंतर यह है कि वैल्यू-टाइप वैरिएबल स्टोर वैल्यूज हैं, इसलिए मेथड कॉल में वैल्यू-टाइप वेरिएबल को निर्दिष्ट करने से उस वेरिएबल के वैल्यू की एक कॉपी पास हो जाती है। संदर्भ-प्रकार चर वस्तुओं के संदर्भों को संग्रहीत करते हैं, इसलिए एक संदर्भ-प्रकार चर को एक तर्क के रूप में निर्दिष्ट करना विधि को वास्तविक संदर्भ की एक प्रति से गुजरता है जो ऑब्जेक्ट को संदर्भित करता है। भले ही संदर्भ स्वयं मूल्य द्वारा पारित किया जाता है, लेकिन विधि अभी भी उस संदर्भ का उपयोग कर सकती है जो उसके साथ बातचीत करने के लिए प्राप्त करता है- और संभवतः मूल वस्तु को संशोधित करता है। इसी तरह, वापसी विवरण के माध्यम से एक विधि से जानकारी वापस करते समय, विधि एक मूल्य-प्रकार चर में संग्रहीत मूल्य की एक प्रति या संदर्भ-प्रकार चर में संग्रहीत संदर्भ की एक प्रति लौटाती है। जब एक संदर्भ वापस आ जाता है, तो कॉलिंग विधि उस संदर्भ का उपयोग संदर्भित ऑब्जेक्ट के साथ बातचीत करने के लिए कर सकती है। इसलिए,
C # में, संदर्भ द्वारा एक चर को पारित करने के लिए तथाकथित विधि चर को संशोधित कर सकती है, C # कीवर्ड को रेफ और आउट प्रदान करता है। एक पैरामीटर घोषणा के लिए रेफरी कीवर्ड को लागू करने से आप संदर्भ द्वारा विधि के लिए एक चर पारित कर सकते हैं - कॉल करने वाले को मूल चर को संशोधित करने में सक्षम होगा। रेफरी कीवर्ड का उपयोग उन चर के लिए किया जाता है जो पहले से ही कॉलिंग विधि में आरंभीकृत किए गए हैं। आम तौर पर, जब एक विधि कॉल में एक तर्क के रूप में एक असंगठित चर होता है, तो संकलक एक त्रुटि उत्पन्न करता है। कीवर्ड आउट के साथ एक पैरामीटर को वरीयता देने से आउटपुट पैरामीटर बनता है। यह संकलक को इंगित करता है कि तर्क को संदर्भ द्वारा बुलाया विधि में पारित किया जाएगा और कहा जाता है कि कॉलर में मूल चर के लिए एक मूल्य प्रदान करेगा। यदि विधि निष्पादन के हर संभव पथ में आउटपुट पैरामीटर के लिए मान निर्दिष्ट नहीं करती है, तो संकलक एक त्रुटि उत्पन्न करता है। यह संकलक को एक असंबद्ध चर के लिए एक त्रुटि संदेश उत्पन्न करने से भी रोकता है जो एक विधि के तर्क के रूप में पारित किया जाता है। एक विधि अपने कॉलर को रिटर्न स्टेटमेंट के माध्यम से केवल एक मान लौटा सकती है, लेकिन कई आउटपुट (रेफ / और / या आउट) मापदंडों को निर्दिष्ट करके कई मान लौटा सकती है।
सी # चर्चा देखें और यहां उदाहरण लिंक पाठ को देखें
उदाहरण:
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const &
आम तौर पर सबसे अच्छा है। आप निर्माण और विनाश का दंड नहीं उठाते। यदि संदर्भ नहीं है, तो आपका इंटरफ़ेस सुझाव दे रहा है कि यह डेटा में पारित कर देगा।
संक्षेप में, पास किया गया मूल्य यह क्या है और संदर्भ द्वारा पारित किया गया है, जहां यह है।
यदि आपका मान VAR1 = "हैप्पी गाइ!" है, तो आप केवल "हैप्पी गाइ!" देखेंगे। यदि VAR1 "हैप्पी गैल!" में परिवर्तित हो जाता है, तो आप यह नहीं जान पाएंगे। यदि यह संदर्भ से गुजरता है, और VAR1 बदलता है, तो आप करेंगे।
यदि आप किसी फ़ंक्शन में पास होने के बाद मूल चर के मूल्य को बदलना नहीं चाहते हैं, तो फ़ंक्शन का निर्माण " पास बाय वैल्यू " पैरामीटर के साथ किया जाना चाहिए ।
तब फ़ंक्शन का केवल मान होगा, लेकिन चर में पारित पते का नहीं। चर के पते के बिना, फ़ंक्शन के अंदर कोड फ़ंक्शन के बाहर से देखे गए चर मान को बदल नहीं सकता है।
लेकिन अगर आप फ़ंक्शन को चर के मूल्य को बदलने की क्षमता देना चाहते हैं जैसा कि बाहर से देखा गया है, तो आपको संदर्भ द्वारा पास का उपयोग करने की आवश्यकता है । चूंकि मान और पता (संदर्भ) दोनों फ़ंक्शन के अंदर और उपलब्ध हैं।
मूल्य द्वारा पास का मतलब है कि तर्कों का उपयोग करके किसी फ़ंक्शन को मान कैसे पास किया जाए। पास में मूल्य से हम चर में संग्रहीत डेटा की प्रतिलिपि बनाते हैं जो हम निर्दिष्ट करते हैं और यह संदर्भ bcse t द्वारा पास की तुलना में धीमा है वह डेटा कॉपी है। हम कॉपी किए गए डेटा में परिवर्तन करते हैं मूल डेटा प्रभावित नहीं होता है। एन डी रेफ़रेन्स द्वारा पास या पते द्वारा पास हम सीधे चर के लिए सीधा लिंक भेजते हैं। या एक चर के लिए सूचक गुजर रहा है। यह तेजी से ई.पू. कम समय खपत है
यहाँ एक उदाहरण दिया गया है जो मान द्वारा पास के बीच के अंतर को दर्शाता है - सूचक मान - संदर्भ :
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
}
"संदर्भ से गुजरना" विधि में एक महत्वपूर्ण सीमा है । यदि एक पैरामीटर को संदर्भ के रूप में पारित किया जाता है (तो यह & संकेत द्वारा पूर्ववर्ती है) इसके संबंधित वास्तविक पैरामीटर को एक चर होना चाहिए ।
"मान द्वारा पारित" औपचारिक पैरामीटर का उल्लेख करने वाला एक वास्तविक पैरामीटर सामान्य रूप में एक अभिव्यक्ति हो सकता है , इसलिए इसे न केवल एक चर बल्कि शाब्दिक या यहां तक कि एक फ़ंक्शन आह्वान के परिणाम का उपयोग करने की अनुमति है।
फ़ंक्शन किसी वैरिएबल के अलावा किसी अन्य चीज़ में मान रखने में सक्षम नहीं है। यह एक शाब्दिक के लिए एक नया मूल्य प्रदान नहीं कर सकता है या इसके परिणाम को बदलने के लिए एक अभिव्यक्ति को मजबूर कर सकता है।
पुनश्च: आप सीधे शब्दों में डायलन बीट्टी के उत्तर की जांच कर सकते हैं जो इसे सीधे शब्दों में समझाता है।