• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
computer notes -  Reference variables
 

computer notes - Reference variables

on

  • 475 views

The “&” indicates a parameter that is a reference variable. Because it is the value that is passed. We can always pass a literal or even an expression in call-by-value computer notes

The “&” indicates a parameter that is a reference variable. Because it is the value that is passed. We can always pass a literal or even an expression in call-by-value computer notes

Statistics

Views

Total Views
475
Views on SlideShare
475
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    computer notes -  Reference variables computer notes - Reference variables Document Transcript

    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________Data StructuresLecture No. 17After demonstrating the use of const and reference variables in the interface class for abinary search tree in the previous lectures, we will now see what these referencevariables are and how does internal process go on during the use of reference variables.Reference VariablesBefore proceeding ahead, there is need to know why the reference variables are used;and what benefits a programmer can get while employing them. We will discuss theseall things in detail with the help of examples.The symbol &, used for reference variable has a few different purposes with respect toits occurrence in the code. In C++ programming, we have seen that when theampersand sign i.e. & appears in front of a variable name, it is the address operator. Itreturns the address of the variable in front of which it is written. Thus for example, if xis a variable name, then &x ; will return the address of the variable x. In general we cansay that &variablename ;will return the address of the variable. We know that an address can be stored in apointer. To further understand this concept, let s suppose that there are following linesin our code. int x ; int* ptr = &x;The first line declares a variable x of type int while the second one declares a pointer toint and assigns it the address of x. This address of variable x is returned by the & signwritten in front of the variable x. Thus a pointer variable is initialized by assigning it theaddress of a variable. This address of the variable is gotten by using the & sign with thevariable name.The other place where & sign can appear is the signature of the function where itappears after the type of the parameter. Consider the insert and remove methods fromBinarySearchTree class that were declared as the following. void insert( const EType& x ); void remove( const EType& x );Notice that the & sign is after the type. Here we define the class and functions astemplates. Whenever, we use these methods, the type EType will be replaced with aproper data type.Suppose that we have designed the BinarySearchTree class to hold the integers only.This means that there are no templates and the class can be defined only for integers. Page 1 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________So the insert and remove methods of this class will be as follows. void insert( const int& x ); void remove( const int& x );Here, in the function signature, & sign after the type of the parameter indicates that theparameter is a reference variable. We can use this & sign with any data type i.e. built-in or user defined, of an argument to show that this is a reference variable. This is thesyntax for the reference variable. Now let s see why and how we use it and what is itsadvantage? Let s look at an example that will explain the reference variable. Supposewe have the following three different functions.The name of the first function is intMinus1, written as under.//Function 1int intMinus1( int oldVal){ oldVal = oldVal 1; return oldVal;}This function takes an integer as an argument. The local name of this argument isoldVal. The first statement in the body of the function decreases the value of oldVal by1 then the next statement returns this value to the calling function.The second function is intMinus2. This function takes a pointer to integer as anargument. In the statement *oldVal = *oldVal 2 ;*oldVal means the value at the location where oldVal is pointing to. To get the valuethis way is called dereferencing. After experiencing a decrease by 2, this value remainsat the same location i.e. where oldVal is pointing to. Then the pointer to integer isreturned. This function is defined as follows.// Function 2int intMinus2( int* oldVal){ *oldVal = *oldVal 2; return *oldVal;}The third function intMinus3 takes a reference variable as an argument. Its definition isas under.// Function 3 Page 2 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________int intMinus3( int& oldVal){ oldVal = oldVal 3; return oldVal;}The & sign after the type in the signature (declaration line) indicates that this argumentis a reference variable. Notice that & sign is used only in the function declaration,leaving no need for its use in the body of the function. The statements in the body ofthe function decrease the vale of oldVal by 3 and return it to the calling function.We can see that these three functions have the same return type and their bodyperforms the task of decreasing the passed value. However it is clear from thedeclaration of these functions that the way of passing argument to these functions isdifferent. We will now see what changes occur while passing the argument in differentways. We will write calling functions those call the above three functions one by one.We will see how these calls are made and what differences happen during the processof passing same value (in different ways) to these functions. The use of call stack willhelp in ascertaining what happens to these local variables and parameters.Following is the function that calls the first function i.e. intMinus1.void caller(){ int myInt = 31; int retVal; retVal = intMinus1( myInt ); cout << myInt << retVal;}In this function (caller), we declare an integer variable myInt and assign it a value 31.We also declare a variable retVal of type int. In the statement retVal = intMinus1( myInt );We call the function intMinus1 by passing it the variable myInt (the value of which is31) and assign the return value of this function call to retVal. In the next statement, weprint the value of these two variables.While talking about runtime environment, we noticed that an executable program whilein run, is loaded in the memory. It later becomes a process. This process is given ablock of memory, which it uses during its execution. Suppose we are running manyprograms simultaneously i.e. browser, MS Word, Excel and dev-C++. We can also runprograms written by us. The figure 17.1 shows that process4 is a program written byus. Every program, which we run takes a block of memory and becomes a process.The memory occupied by a process is further partitioned into different parts. The firstpart of the memory is for the code of the program. This code is in binary form i.e. it isthe compiled code. Afterwards, there is some area of memory for static data that holdsstatic and global variables. Then in the memory, there becomes the stack. This stack isused in function calls. At the end, there is some area, called heap. When we allocate Page 3 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________memory dynamically by using new operator, this memory is allocated from the heap.The following figure shows the internal memory organization of a program(ourtest.exe). Process 1 Code (browser) Process 3 Static data (Word) Stack Process 4 (ourtest.exe) Process 2 (Dev-C++) Windows Os Heap Fig 17.1: Internal memory organization of a process (ourtest.exe)We have discussed in detail the call stack that is used in function calls. We know thatwhen a function call is made, it s all the arguments go on the stack. The return addressof the function also goes to the stack. The local variables are placed on the stack.When a function calls some other function, an activation record is made. It has muchinformation including all these things (parameters, return address etc). The detail ofactivation record relates to the compiler construction course. Here we are concernedwith only the call stack. Following figure shows the call stack layout. Parameters (caller) Local variables(caller) Return address (caller) Parameters (intMinus1) Local variables(intMinus1) Return address sp (intMinus1) stack grows downwards Fig 17.2: call stack layoutIn the stack layout figure, there are the entries of the caller in the upper portion. This isdue to the fact that the caller function itself was called (executed) by some one else. Page 4 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________The lower portion of the stack describes the stack status when the function intMinus1is called. The stack contains parameters, local variables and return address of thefunction intMinus1. There is a stack pointer sp that points to the top of the stack (thefigure shows the stack downward; it should not be confused with the top). As thecaller has called intMinus1, this function is on the top of the stack.The following figure shows the contents of the stack when the function intMinus1 iscalled. 1072 31 myInt 1068 ? retVal calling function caller callers other stuff 1060 31 oldVal 1056 Called function intMinus1 1052 sp stack grows downward Fig 17.3: call stack layout when intMinus1 is calledThe figure shows the stack in two parts. The first part that is in the upper curlybracket, shows the contents of the calling function i.e. caller. The lower part shows thecontents of the called function i.e. intMinus1. Recall that we declared two variables inthe caller function. These variables were myInt and retVal. We also assigned a value 31to myInt. This value (31) is in the memory location of myInt in the stack. When wedeclared the variable retVal, there was no value assigned to it. So its memory locationcontains nothing yet. After it, there is the other stuff of the caller function. We havealso shown the memory addresses of the locations on the left hand side. We can seethat the memory address of myInt is 1072 while that of retVal is 1068. Similarly, wesee the addresses 1060, 1056 and 1052 further down. We note that the addresses arewith a difference of four. This is because of the use of the integer variable, as aninteger requires four bytes in the memory for storing. Similarly the pointer variables arealso of four bytes. The memory addresses are in 32 bits that is four bytes (eight bitsmake a byte). Generally we start addressing the memory from down. The lowest byteis addressed 0, followed by 1, 2, 3 and so on to upward direction. If we have largervariables, for example, objects created by our defined classes, these will require morememory. In that case, the memory chunks will not be of four bytes. Rather, it will beequal to the size of the object. In C++, we have an operator size or sizeof by which thesize of a type or variable, acquired in the memory, can be found. There are somemachines that do not use byte addressing. These machines use word addressing. Everyword is of 48 bits. All these things (memory addressing etc) relate to computerarchitecture course. Page 5 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________Now in the stack, there are the entries of the called function. There is the parameteroldVal of the called function in the stack. It has the value 31. This is the same value asthat of myInt in the caller function. As studied earlier, in call by value phenomenon,when arguments (whatever type they have) are sent to a function, a copy of thesearguments is made before sending. That copy is sent to the called function. The calledfunction uses this copy of the argument. Thus a copy of myInt is passed to the calledfunction intMinus1. Thus its parameter oldVal has value 31. Now intMinus1 functionuses this value (i.e. oldVal) to do its functionality. It makes alternations to this copy.The original value that is myInt does not change. This phenomenon is shown in thefollowing figure. Here the function intMinus1 decreases the value of oldVal by 1 andbecomes 30. The original value (myInt) remains unchanged. 1072 31 myInt 1068 ? retVal calling function caller callers other stuff 1060 31 30 oldVal 1056 Called function intMinus1 1052 sp stack grows downward Fig 17.4: call stack layout after subtraction in intMinus1When the return call of intMinus1 is executed, the control comes back to the callingfunction. The stuff of the called function intMinus1 is popped from the stack and thepointer sp moves up accordingly. In other words, the activation record of the functionintMinus1 has been removed from the stack. The oldval (value of which is 30 now) isreturned to the caller function. We have written in the code that this value is assignedto retVal variable. So in the call stack layout, the memory location of retVal has thevalue 30. The figure 17.5 shows the stack layout after return from the called functioni.e. intMinus1. 1072 31 myInt 1068 30 retVal calling function caller callers other stuff sp stack grows downward Fig 17.5 call stack layout after return from intMinus1 Page 6 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________In the call by value phenomenon of function calling, we can pass a literal or even anexpression. Thus in the previous function caller, we could have called the functionintMinus1 as follows.void caller(){ int retVal; retVal = intMinus1( 31 ); // a literal is passed cout << retVal;}Here we did not put the value 31 in an integer variable. Rather, it was directly passedas an argument in the function call i.e. intMinus1 (31). We are not passing a variable asit was in the previous code of the function caller. The calling statement also be writtenas under: retVal = intMinus1( 30 + 1 );In this statement, first the expression 30 + 1 is evaluated and then the copy of theresult goes to the call stack as a value of oldVal of called function.In the previous calling function (i.e. caller), it was witnessed that the value of thepassed variable (myInt) remained same when we passed the variable by value. Nowthere may be situations where we want to actually change the value of a variable of thecaller function from within the called function. In such a situation, we send the pointerto the variable (i.e. the address of the variable) as an argument. Look at the followingcode of the function caller. In this code, we call the function intMinus2 by passing itthe address of the variable myInt.void caller(){ int retVal; int myInt = 31; retVal = intMinus2( &myInt ); cout << myInt << retVal;}Following is the function calling statement retVal = intMinus2( &myInt );The & sign before the name of the variable myInt means that the address of thevariable is being passed. The called function will take it as a pointer. Remember thatwe have declared the argument of the function intMinus2 as int* oldVal that meansthis function takes a pointer as an argument.Now, keeping in mind that a pointer is being sent to the function, let s see what ishappening in the call stack. The stack portion which has the stuff of the calling functioni.e. caller is the same as seen in the call by value process. The variable myInt has value31 and value of retVal will be written after returning from the called function. Its stack Page 7 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________layout is shown in the figure 17.6 below. 1072 31 myInt 1068 ? retVal calling function caller callers other stuff 1060 1072 oldVal 1056 Called function intMinus2 1052 sp stack grows downward Fig 17.6 call stack layout when intMinus2 is calledIn the stuff of the called function i.e. intMinus2, the memory location of the oldValholds the value 1072. We can see on the left side of the stack in the figure above thatthis 1072 is the address of the variable myInt. Look at the statement *oldVal = *oldVal 2 ;of intMinus2. Here *oldVal can be expressed as the value at the memory address thatis in oldVal . In the stack layout, we see that the memory address in oldVal is 1072.The value stored at the address 1072 is 31. The following statement *oldVal = *oldVal 2 ;decreases this value 2 and thus brings the value at the memory address 1072 down to29. As 1072 is the address of myInt, thus actually the value of myInt is changed. Thefollowing figure of stack layout depicts this process. 1072 31 29 myInt 1068 ? retVal calling function caller callers other stuff 1060 1072 oldVal 1056 Called function intMinus2 1052 sp stack grows downward Fig 17.7: call stack layout after *oldVal = *oldVal 2; Page 8 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________Now when the execution of the called function ends after returning *oldVal, theactivation record of this function is removed from the stack. The pointer of the stackcomes up. The value 29 is put in the variable retVal of the calling function. Followingis the stack layout after return from the function intMinus2. 1072 31 29 myInt 1068 29 retVal calling function caller callers other stuff sp stack grows downward Fig 17.8: call stack after return from intMinus2Notice that the value of myInt of the caller function has also been changed.We have seen that in call by value a copy of the argument is passed and used by thecalled function. In this method, the original value of the argument in the callingfunction remains unchanged. In the other method, we saw that when we pass theaddress of the variable, the pointer is used to manipulate the variable data. In this case,the original value of the variable in the calling function is changed. Suppose that wewant a function to change an object (variable/argument) but don t want to send thecopy of the object to the function. The reason of not sending a copy is that the objectmay be large (as we have seen the object Customer in bank simulation example) andmaking a copy of it costs time and memory space. Say, the object Customer is of 500bytes. Now when a calling function will call a function using call by value method, acopy of this object will be made on the call stack same as in our previous example acopy of myInt was made. The copy constructor will make a copy of this whole objectthat costs time. Moreover, the copy of this object will take 500 bytes on the stack thatis a lot of memory consuming. There will be as many copies as the number of calls. Incase of a large number of calls, there may be inefficient memory as call stack has alimited memory. So we do not use call by value methodology. Furthermore, we wantto avoid the massive syntax of pointers. For this purpose, we do not use pointers infunction calling. Now the question arises is there any way through which we can fulfillour requirement. (i.e. we don t want to make a copy and want to change the objectivewithout using the pointers ). The use of reference variables may be a suitable answer tothis very ticklish situation. The phenomenon of function calls using reference variables Page 9 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________is termed as call by reference. Following is the code of the caller function that involvescall by reference.Void caller(){ int retVal; int myInt = 31; retVal = intMinus3( myInt ); cout << myInt << retVal;}Note that this is almost the same function, we wrote at first to call intMinus1. The onlydifference is that here we are calling the function intMinus3 instead of intMinus1. Wedid not use & sign with myInt as used in the call for intMinus2. This is only due to thefact that we are not sending an address. It is pertinent to note that in the definition ofthe function intMinus3, we have used & sign with the argument variable. We havewritten it as int intMinus3( int& oldVal)This statement means that the function intMinus3 will take a reference as an argument.In other words, a reference of the argument variable will be passed to this function.Thus the idea of reference variable is that an object will be used exactly as it exists inthe caller function. The called function simply accesses it through a different name i.e.other than the name in the caller function. Here in our example, the called functionintMinus3 accesses (and uses) the passed argument i.e. myInt with the name oldVal.The function intMinus3 cannot use the name myInt as it is in the caller s scope. Nowthe both variable names (myInt and oldVal) refer to the same object. It means that thesame memory cell where the object lies. We have read the scope of variables that thelocal variables can be used only by the function in which they are declared. The otherfunctions cannot use the local variables of a function. But in reference variables, wecan access the memory location of a local variable in another function by using anothername. Thus in our example, we access the local variable myInt (actually the memorylocation) of the function caller in the other function intMinus3 with the name oldVal.The following figure explains this phenomenon of reference variables with the help ofcall stack layout. 1072 31 myInt 1068 ? retVal calling function caller callers other stuff 1060 oldVal 1056 called function intMinus3 1052 sp stack grows downward Page 10 of 3 Fig 17.9: call stack when intMinus3 is called
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________The caller function part of the stack contains myInt, retVal and other stuff of the callerfunction. In the stack part intMinus3, the name oldVal shows that it has nothing in thisportion but it is the other name of the memory location 1072, named as myInt in thecaller function. The dotted arrow shows this.In the following figure 17.10, we show the oldVal along with the myInt at samememory location. Here we want to show that the oldVal of called function and myIntof caller function are the two names of the same memory location. OldVal 31 myInt 1072 ? retVal calling function caller 1068 callers other stuff 1060 called function intMinus3 sp 1056 1052 stack grows downward Fig 17.10: call stack when intMinus3 is clledNow when the body of the intMinus3 executes the statement i.e. oldVal = oldVal 3 ;It changes the value at the memory location in the caller function as it is referring tothat memory location. This value now becomes 28. Actually, the value of myInt ischanged as it also refers to the same memory location. The following figure explainsthe stack lay out after the execution of the above statement. oldVal 1072 31 28 myInt ? retVal 1068 calling function caller callers other stuff 1060 called function Page 11 of 3 intMinus3 1056 sp
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________Now when the function intMinus3 returns, the returned value (that is 28) is written inretVal and the stuff (activation record) of intMinus3 is removed. The stack layoutbecomes as shown in the figure below. 1072 31 28 myInt 1068 28 retVal calling function caller callers other stuff sp stack grows downward Fig 17.12: call stack layout after return from intMinus3This phenomenon of call by reference is actually implemented by the compiler by usingpointers. The obtaining of address and de-referencing will be done behind the scene.We have no concern to do this. For a programmer, it is simply a renaming abstraction,in which we rename the argument variable of the caller function and use it in the calledfunction.Sample ProgramFollowing is the program, which demonstrate the above three function calls that wediscussed in the previous example. We define the three functions intMinus1, intMinus2and intMinus3. These functions accept the argument as value, pointer and referencevariable respectively. The endl puts a new line and is used in the program for theoutput clarity. Here is the code of the program followed by the output of the program./*This program demonstrate tha how the value in a caller function is effected when it ispassed to a function by using call by value, by using pointers and by using call byreference methods.*/#include <iostream.h> Page 12 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________//Function 1, call by valueint intMinus1( int oldVal){ oldVal = oldVal 1; return oldVal;}// Function 2, call by using pointersint intMinus2( int* oldVal){ *oldVal = *oldVal 2; return *oldVal;}// Function 3, call by referenceint intMinus3( int& oldVal){ oldVal = oldVal 3; return oldVal;}void main (){ int myInt = 31; int retVal; retVal = intMinus1( myInt ); //call by value cout << After returning from the called function intMinus1 << endl ; cout << The value returned by the called function (retVal) is : << retVal ; cout << endl ; cout << The value of the calling function s variable (myInt) is : << myInt ; cout << endl << endl; // now pass the argument by using pointer, also initialize the value of myInt myInt = 31 ; retVal = intMinus2( &myInt ); //call by passing a pointer cout << After returning from the called function intMinus2 << endl; cout << The value returned by the called function (retVal) is : << retVal ; cout << endl; cout << The value of the calling function s variable (myInt) is : << myInt ; cout << endl << endl; // now pass the argument by as reference, also initialize the value of myInt Page 13 of 3
    • ecomputernotes.com Data Structures Lecture No. 17___________________________________________________________________ myInt = 31 ; retVal = intMinus3( myInt ); //call by passing a reference cout << After returning from the called function intMinus3 << endl; cout << The value returned by the called function (retVal) is : << retVal ; cout << endl; cout << The value of the calling function s variable (myInt) is : << myInt ;}Following is the output of the program.After returning from the called function intMinus1The value returned by the called function (retVal) is : 30The value of the calling functions variable (myInt) is : 31After returning from the called function intMinus2The value returned by the called function (retVal) is : 29The value of the calling functions variable (myInt) is : 29After returning from the called function intMinus3The value returned by the called function (retVal) is : 28The value of the calling functions variable (myInt) is : 28We can see from the output of the program how the passed variable of the callerfunction is affected by these different ways of function calling. Note that the values ofthe variables used are the same as we have discussed with the help of call stack layout. Page 14 of 3