Reference Variable in C++: Reference Argument किसी Variable का एक दूसरा नाम यानी “Alias” होता है। जब हम किसी Argument को किसी Function में Pass करते हैं, तो वह मान Function में Create होने वाले किसी Automatic Variable में Copy हो जाते हैं। फिर हम उस Argument के मान पर किसी भी प्रकार की प्रक्रिया करें, हमारे Program के Original मान में किसी प्रकार का कोई परिवर्तन नहीं होता है। क्योंकि Function उस समय Variable के Original मान को Access नहीं करता है बल्कि उस मान की प्रतिलिपी को Access करता है।
लेकिन यदि हम चाहें कि Function में किसी Variable के Original मान पर कि Function Perform हो, तो हमें एक ऐसा तरीका Use करना पडता है, जिसमें Function Argument के रूप में आने वाले किसी Variable के Actual मान को Access करे ना कि उसकी प्रतिलिपी को।
Reference Variable in C++ – Swapping Integers
मानलो, कि हमारे पास दो Integer Variables हैं और हम इन दोनों Variables के मानों को आपस में Exchange करना चाहते हैं। जैसे:
int alpha = 2;
int beta = 7;
Reference Variable in C++ – Passing by Value
इस काम के लिए हम निम्नानुसार एक swap Function Call कर सकते हैं:
void swap(int a, int b) // function swaps values { int temp = a; a = b; b = temp; }
यदि हम alpha व beta के मानों को आपस में Exchange करना चाहें, तो इस Function को निम्नानुसार Call कर सकते हैं:
swap(alpha, beta);
आप सोचेंगे कि इन दोनों Variables के मान एक दूसरे से Exchange हो गए हैं, लेकिन वास्तव में यदि आप इन दोनों Variables को Print करेंगे, तो आपको पता चलेगा कि दोनों के मान में कोई परिवर्तन नहीं हुआ है। ऐसा इसलिए हुआ है क्योंकि Function में Variables के मानों की केवल Copy Pass हो रही है, Actual Variable Pass नहीं हो रहा है।
Reference Variable in C++ – Passing by Reference
चूंकि हम Function में Pass किए जा रहे Arguments के Actual मानों को Change करना चाहते हैं, इसलिए हमें एक ऐसे तरीके की जरूरत है जिसमें Function Arguments के Actual मानों तक पहुंच सकें और उन्हें Manipulate कर सकें। “C” में हम इस काम को करने के लिए Pointers का प्रयोग करते थे। लेकिन “C++” में हमारे पास Pointers के अलावा एक और तरीका भी है, जिससे ये काम कर सकते हैं। इस तरीके को Passing By Reference कहा जाता है।
जब हमें किसी Variable के Actual मान को किसी Function में Pass करना होता है, तब हमें Function के Data Type के साथ केवल एक & का प्रयोग करना होता है। उदाहरण के लिए यदि हम swap() Function में Arguments के Actual मानों को भेजना चाहें, तो हमें swap() function को निम्नानुसार Modify करना होगा:
void swap(int& a, int& b) // function swaps values { int temp = a; a = b; b = temp; }
अब यदि हम alpha व beta के मानों को इस Function में निम्नानुसार Pass करके Output में Print करें, तो हम देख सकते हैं कि दोनों Variables का मान आपस में Exchange हो गया है। जब हम Function के Parenthesis में Data Type के साथ & का प्रयोग करते हैं, तब Compiler समझ जाता है, कि इस Function में किसी Variable का Actual मान आएगा और Function को Argument के Actual मानों पर प्रक्रिया करनी है। इस प्रकार का Declaration Actual Arguments का Reference होता है।
वास्तव में Reference एक ही Variable का एक दूसरा नाम होता है और दोनों ही नाम समान Memory Location के होते हैं। यानी यदि alpha Variable Memory Location 100 का नाम है तो Reference Argument a भी Memory Location 100 को ही Represent कर रहा होता है।
चूंकि Objects भी वास्तव में एक नए प्रकार का Variable ही होता है, इसलिए हम किसी Object की भी इसी प्रकार से Swapping कर सकते हैं। इसे समझने के लिए employee Class के दो Objects को Exchange करने का Program निम्नानुसार दिया जा रहा है।
// Program #include <iostream.h> #include <conio.h> const int SMAX = 21; // maximum length of strings class Employee { private: char name[SMAX]; // name (20 chars max) int serialNumber; public: void input() // get data from user { cout << " Enter name: "; cin >> name; cout << " Enter serial number: "; cin >> serialNumber; } void output() // display employee data { cout << " Name = " << name; cout << "\n Serial number = " << serialNumber; } }; void main() { void swap(Employee&, Employee&); // declaration Employee Employee1, Employee2; cout << "Enter data for employee 1" << endl; Employee1.input(); cout << "Enter data for employee 2" << endl; Employee2.input(); cout << "Swapping employee data"; swap(Employee1, Employee2); // swap employees cout << "\nData for employee 1" << endl; Employee1.output(); cout << "\nData for employee 2" << endl; Employee2.output(); getch(); } // end main() // User Defined Object swapping Function void swap(Employee& Emp1, Employee& Emp2) // definition { Employee temp = Emp1; Emp1 = Emp2; Emp2 = temp; } // Output Enter data for employee 1 Enter name: NandLal Enter serial number: 123 Enter data for employee 2 Enter name: BalGopal Enter serial number: 321 Swapping employee data Data for employee 1 Name = BalGopal Serial number = 321 Data for employee 2 Name = NandLal Serial number = 123
Main Program में दो Employees प्रकार के Objects Create किए गए हैं और उनमें Data Input करने के लिए User को Prompt किया गया है। User जब दो Employees के Data Input कर देता है, तब Program दोनों Objects के Name Data Member को Exchange कर देता है और दोनों Object के Exchanged Data को Output में Print कर देता है।
हम देख सकते हैं कि यहां पर swap() Function को Employee Class का Member Function होना जरूरी नहीं है, क्योंकि ये Employee Class के किसी Private Instance Data या Private Data Member से Interaction नहीं कर रहा है।
References को हम Standalone Variables की तरह भी Use कर सकते हैं। हालांकि हम ऐसा करें इसकी जरूरत Real Program में नहीं पडती है। इसे समझने के लिए सबसे पहले एक Variable Create करते हैं और उस Initialize करते हैं। यानी
int intVariable = 21;
अब इसका निम्नानुसार एक Reference बनाते हैं:
int& intRerference = intVariable;
जब हम किसी Variable का कोई Reference बनाते हैं, तो Reference बनाते समय ही हमें ये भी बताना पडता है, कि हम जो Reference बना रहे हैं, वह Actually किस Variable को Reference करेगा।
इसीलिए हमने यहां पर int& intReference = intVariable; Statement द्वारा intReference को Declare करते ही उसे intVariable Assign किया है, जिसका मतलब ये है कि ये intReference intVariable को ही Refer करेगा। यानी यदि हम इन दोनों नामों को एक दूसरे के स्थान पर Use कर सकते है। ऐसा करने पर भी प्राप्त होने वाले परिणाम व सम्पन्न होने वाली प्रक्रिया में किसी प्रकार का कोई अन्तर नहीं आएगा।
यदि हम Reference Declare करते ही उसे किसी Variable का नाम Initialize ना करें, तो Compiler Error Generate करता है। जब हम किसी Function Argument के रूप में References का प्रयोग करते हैं, तब ये Initialization स्वयं ही हो जाता है। अब यदि हम दोनों Variables के मानों को Print करें तो हमें निम्नानुसार Output प्राप्त होता है:
cout << “\n Variable = “ << intVariable ; // Output : Variable = 21
cout << “\n Reference = “ << intReference; // Output : Reference = 21
हम देख सकते हैं कि दोनों ही Statements का Output समान प्राप्त होता है। इसका कारण यही है कि दोनों ही Variables या दोनों ही नाम एक ही Memory Location को Access कर रहे हैं। यानी दोनों ही नाम एक ही Memory Location के हैं। यदि हम किसी एक भी Variable का मान Change कर दें, तो दूसरा Variable भी उसी Changed मान को Display करता है। जैसे-
intReference = 210;
cout << “\n Variable = “ << intVariable ; // Output : Variable = 210
cout << “\n Reference = “ << intReference; // Output : Reference = 210
एक Reference को केवल एक ही बार Define व Initialize किया जा सकता है। यदि एक बार Defined व Initialized Reference को दुबारा किसी दूसरे Variable का Reference प्रदान किया जाता है, तो Compiler Error Generate करता है।
जब किसी Reference को Define व Initialize किया जाता है तब Compiler Reference को Define व Initialize करने के लिए Actual Variable का Address Use करता है। “C” Programmers समझ सकते हैं कि References वास्तव में कुछ हद तक Pointers के समान Behave करते हैं।
फिर भी References Pointers की तुलना में Use करने में सरल होते हैं क्योंकि इन्हें Dereference नहीं करना पडता है और Compiler हमेंशा इस बात के लिए बा/; करता है कि हम Reference को Define करते ही उसे किसी ना किसी Variable के मान से Initialize करें।
इसलिए इसकी सम्भावना बहुत ही कम होती है कि हम किसी Reference का Pointers की तरह गलत प्रयोग करें और हमारे Program में किसी तरह की Critical error Generate हो। हालांकि References उपयोग करने में काफी सरल हैं, लेकिन ये Pointers जितने Powerful नहीं हैं।
जब हम किसी Function में किसी Variable के मान को By Value भेजते हैं, तब Variable के Actual Data के किसी कारण से नद्गट होने की सम्भावना नहीं होती है। इसलिए जब Basic Data Type के Variables Use कर रहे होते हैं, तब Variables के मानों को किसी Function में By Value भेजना उचित रहता है। लेकिन जब हम Objects को किसी Function में Pass करना चाहते हैं, तब Objects को Functions में By Reference भेजना ज्यादा ठीक रहता है।
क्योंकि यदि हम Objects को By Value भेजते हैं, तो Object के मानों को Hold करने के लिए Function एक Temporary Object Create करता है और उसी Temporary Object को पूरे Function में Use करता है। अक्सर Objects काफी बडे होते हैं, इसलिए यदि किसी Object को कई बार कई Functions में By Values Pass किया जाए, तो उस Object की कई Copies बनती है, जिससे Memory Waste होती है। इसलिए विभिन्न प्रकार की समस्याओं से बचने के लिए Objects को किसी Function में By Reference ही भेजना उचित रहता है।
Reference Variable in C++ – Returning by Reference
जिस तरह से हम विभिन्न प्रकार के Basic व User Defined Data Type के मानों को किसी Function से Return करवा कर उन्हें विभिन्न प्रकार से उपयोग में ले सकते हैं उसी तरह से हम किसी भी प्रकार के Variable या Object का Reference भी किसी Function से Return करवा सकते हैं।
किसी मान को By Reference Return करवाने का एक कारण ये भी है कि Function Call करने के Expression को Equal to ( Assignment Operator) के Left Side में भी Use कर सकते हैं और Function को उसी प्रकार से कोई मान प्रदान कर सकते हैं जैसे हम किसी Variable को मान प्रदान करते हैं।
उदाहरण के लिए यदि हमारे पास एक Object xyz और एक Member Function getAndSet() है, तो हम इसे निम्नानुसार Use कर सकते हैं:
xyz.getAndSet() = 210;
ये Statement देखने में काफी अजीब लग सकता है। सामान्य तौर पर हम किसी Function को इस प्रकार का Assignment नहीं कर सकते हैं क्योंकि Compiler किसी Function Call को एक Variable की तरह नहीं मानता है जिसमें किसी प्रकार का मान Assign किया जा सके।
इसके बजाय Compiler Function को एक Constant की तरह मानता है, जिसका मान किसी अन्य Variable को तो दिया जा सकता है लेकिन स्वयं का मान Change नहीं किया जा सकता है। हम किसी Function को सामान्य तौर पर उसी प्रकार से Assignment Operator के Left Side में Call नहीं कर सकते जिस प्रकार से निम्न Statement को Use नहीं किया जा सकता:
21 = intVariable;
हम ऐसा Statement इसलिए Use नहीं कर सकते हैं क्योंकि 21 एक Constant है और कोई Constant मान कभी भी Equal To Sign के Left Side में Use नहीं किया जा सकता है। कोई भी Identifier जिसे कोई मान प्रदान किया जा सकता हो, उस मान को lvalue कहते हैं, क्योंकि ये मान सामान्यतया left Side के Variable को प्रदान किया जाता है। जबकि Equal To Sign के Right Side में हमेंशा एक Constant होता है, जो किसी Variable को Assign होता है, इसलिए इसे rvalue कहा जाता है।
निम्न Program देखिए, जिसमें एक Function Define किया गया है जो एक Reference Return करता है। इस Program में हम ये Demonstrate कर रहे हैं कि हम किस प्रकार से किसी Reference Return करने वाले Function को Equal To Operator के Left Side में Use कर सकते हैं और किसी Object को इस तरीके से Function को Call करके कोई मान प्रदान कर सकते हैं।
// Program #include <iostream.h> class Omega { private: int data; public: int& getAndSet() // returns OR SETS data { // (note ampersand) return data; } }; void main() { Omega om1; // make an object om1.getAndSet() = 192; // give it a value (!) cout << "om1 = " << om1.getAndSet(); // get the value and display it }
इस Program के main() Function में getAndSet() Member Function को दो बार Call किया गया है। दूसरी बार किया गया Call Normal तरीके का Call है। लेकिन पहला Call Equal To Sign के Left Side में किया गया है। चलिए, इस तरीके को समझते हैं। पहली बार इस Function को निम्नानुसार Call किया गया है:
om1.getAndSet() = 192;
ये Statement om1 Object के Data Member data को मान 192 Assign कर देता है। ऐसा हो सके, इसके लिए दो बातें होनी जरूरी हैं। पहली ये कि Function getAndSet() को इस प्रकार से Defined किया गया होना चाहिए कि वह Reference Retrun करे। ये काम हम Return Data Type के साथ & Operator का प्रयोग करके पूरा करते हैं। यानी
Int& getAndSet();
और दूसरा ये कि Function Object के उस Variable data को Return करे, जिसे Assign किया गया मान प्रदान करना है। इसके लिए Function के अन्दर निम्न Statement लिखते हैं:
return data;
main() Function जो 192 मान Function को प्रदान करता है, वह मान Opposite Direction द्वारा Function में जाता है और Object के Data Member data को प्राप्त होता। उसके बाद Data Member data का मान main() Function को Return होता है। इस प्रकार से Program का Output निम्नानुसार प्राप्त होता है:
om1 = 192;
ये Statement बताता है कि एक ही Function getAndSet() द्वारा हम किसी Object में मान को Input भी कर सकते हैं और मान को Output में Display भी कर सकते हैं।
एक बात हमेंशा ध्यान रखें कि कभी भी किसी Function से किसी Automatic Variable जिसे Function की Body में Define व Declare किया गया हो, का Reference Return ना करे। क्योंकि Program Control जैसे ही किसी Function से Return होता है, उस Function के सारे Automatic Variables Destroy हो जाते हैं, इसलिए जो Reference Function से Return होगा, वह किसी Garbage Memory Location को ही Represent करेगा।
Function से Reference Return करने का तरीका “C++” में इसलिए Create किया गया था ताकि Overloaded Functions से Return होने वाले मानों को Handle किया जा सके। इसके अलावा इसका कोई विशेष उपयोग नहीं किया जाता है। (Reference Variable in C++ – Wiki)
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
C++ Programming Language in Hindi | Page: 666 | Format: PDF