/******************************************************************* Passing pointers by reference This program is written help show why and how you would pass a pointer by function. What you can do with and to a pointer is determined by the manner in which it is passed (pass-by-value, pass- by-reference). If a pointer is passed into a function by value, the function gets a COPY of the value stored in the pointer. Using that value the function can access and manipulate the data stored in the memory location pointed to by the pointer. Any changes to the data POINTED to will be visible in back in the calling function (in this case main()). However, if the value of the pointer is modified within the function, those changes will be lost when the function exits and the function's pointer variable name goes out of scope. If a pointer is passed into a function by reference, the function actually gets the ADDRESS of the pointer. NOTE THAT THE FUNCTION GETS THE ADDRESS OF THE POINTER VARIABLE, NOT THE THE VALUE (ADDRESS) STORED BY THAT POINTER! By giving the address of the pointer, the function has access to the actual pointer and can manipulate the pointer, just as in pass-by- reference with any other variable type. Any changes to the value of the pointer will be visible back in the calling function. LT Johnson USNA Computer Science Department November 2007 *******************************************************************/ #include using namespace std; //This function passes a pointer by value, and does not explicitly //return anything. Any changes made to the pointer inside the funciton //will not be visible to the calling function. void arrayByValue(int*); //This function passes a pointer-by-reference. It does not explicitly //return any results. Passing by reference allows the function to //modify the value of the variable passed to it, in this case an int*. void arrayByReference(int *&); //This function takes a pointer through pass-by-value. Any changes that //the function makes to the value of the pointer passed to it will be //lost when the function returns. The return value (int*) is how this //function affects any change in the calling function. int* arrayPassAndReturn(int*); int main() { int i; char junk; //Create an array of integers of size 5 //have an int pointer, B, point to the array. // B----->[][][][][] int* B = new int[5]; //note the array contains //no values at this time. int* B2 = B; //the int* B2 will also point //to the same array (place in //memory) as B. // B----->[][][][][] // B2-----^ ////////////////////////////////////////////////////////////////////// ////////A REPEAT OF THE COMMENTS AT THE BEGINNING OF THE FILE///////// cout << "I recommend maximizing the console window before proceeding.\n"; cout << "That way you can see more of the output without having to scroll.\n\n"; cout << "Press ENTER to continue."; junk = cin.get(); system("cls"); cout << "What you can do with and to a pointer is determined by\n"; cout << "the manner in which it is passed (pass-by-value, pass-\n"; cout << "by-reference).\n\n"; cout << "If a pointer is passed into a function by value, the\n"; cout << "function gets a COPY of the value stored in the pointer.\n"; cout << "Using that value the function can access and manipulate\n"; cout << "the data stored in the memory location pointed to by the\n"; cout << "pointer. Any changes to the data POINTED to will be visible\n"; cout << "in back in the calling function (in this case main()).\n"; cout << "However, if the value of the pointer is modified within the\n"; cout << "function, those changes will be lost when the function exits\n"; cout << "and the function's pointer variable name goes out of scope.\n\n"; cout << "If a pointer is passed into a function by reference, the\n"; cout << "function actually gets the ADDRESS of the pointer. NOTE THAT\n"; cout << "THE FUNCTION GETS THE ADDRESS OF THE POINTER VARIABLE, NOT THE\n"; cout << "THE VALUE (ADDRESS) STORED BY THAT POINTER! By giving the\n"; cout << "address of the pointer, the function has access to the actual\n"; cout << "pointer and can manipulate the pointer, just as in pass-by-\n"; cout << "reference with any other variable type. Any changes to the value\n"; cout << "of the pointer will be visible back in the calling function.\n\n"; cout << "Press ENTER to continue."; junk = cin.get(); system("cls"); ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// cout << "In main:\n"; cout << "The address that, int* B points to: " << B << endl; cout << "The address that, int* B2 points to: " << B2 << endl; //call the function arrayByReference() and pass //it the int* B //as in all pass-by-reference parameters, what the //receiving function, in this case arrayByReference, //receives is not the value stored in B, but rather //the address in memory where B is stored. //Doing this allows the function to directly access //and manipulate the variable, rather than a copy of //the original value. cout << "First let's print the arrays that B and B2 point to:\n"; for(i = 0; i < 5; i++) { cout << "B[" << i << "] = " << B[i] << "\t\tB2[" << i << "] = " << B2[i] << endl; } cout << "Since they both point to the same address and the array\n"; cout << "is not initialized, we have garbage.\n"; cout << "Press ENTER to continue."; junk = cin.get(); cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "\n\nNow lets call a function which will take a pointer,\n"; cout << " pass-by-value, and create an array.\n\n"; cout << "We will pass in int* main::B (address: " << B << ") and see what happens.\n\n"; arrayByValue(B); cout << "Press ENTER to continue."; junk = cin.get(); cout << "\n\nNow that we're back in main() let's print out the array we just made.\n"; cout << "Remember, we passed the int*, B, into the function, so it should point\n"; cout << "to the array filled with 3's.\n"; cout << "main::B = " << B << endl; for(i = 0; i < 5; i++) cout << "B[" << i << "] = " << B[i] << endl; cout << "main::B still points to the same address it did before the function! And\n"; cout << "where did our array of 3's go? The array is still in memory (remember,\n"; cout << "objects created with the \"new\" command don't have a scope) but when we\n"; cout << "left the function the variable arrayByValue::arrayPtr went out of scope and was\n"; cout << "destroyed, taking with it the address of the array, and the only way we had to\n"; cout << "access it. In effect we have lost any changes we made to the original input/n"; cout << "variable values because we passed a COPY of the value, and it was thrown away/n"; cout << "at the conclusion of the functions execution.\n"; cout << "Press ENTER to continue."; junk = cin.get(); cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; arrayByReference(B); //Because this function received B as a call-by-reference, //any changes to the address the integer pointer points to //will be reflected here in main as well. cout << endl << "Now that arrayByReference(int*) has been called\n"; cout << "The address that int* B points to: " << B << endl; cout << "The address that int* B2 points to: " << B2 << endl; cout << "NOTE: B points to the same address as arrayPointer from the\n"; cout << "function, arrayByReference(). B now points to a new address but\n"; cout << "B2 still points to the original address with uninitalized data.\n\n"; cout << "Now let's print the arrays that B and B2 point to:\n"; cout << "int* B: " << B << "\t" << "int* B2: " << B2 << endl; for(i = 0; i < 5; i++) cout << "B[" << i << "] = " << B[i] << "\t\tB2[" << i << "] = " << B2[i] << endl; cout << "Press ENTER to continue."; junk = cin.get(); cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; //So right now our pointers look like this: // B----->[1][1][1][1][1] // B2---->[][][][][] //call the pass and return function B2 = arrayPassAndReturn(B); //Since this function utilizes pass-by-value, a COPY of the address pointed to by B //was passed into the function. The function can do anything it wants to the copy it //receives but it will not effect the original value which is safely stored in main::B //After the function, arrayPassAndReturn(), returns B2 will hold the value of the address //that was retuned to it by the function. In this case B2 will point to an array filled with 2's. cout << "Press ENTER to continue."; junk = cin.get(); cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "\n\nNow that the function, arrayPassAndReturn, has returned let's print the\n"; cout << "addresses that B and B2 point to as well as the two arrays they point to.\n"; cout << "int* B: " << B << "\t" << "int* B2: " << B2 << endl; for(i = 0; i < 5; i++) cout << "B[" << i << "] = " << B[i] << "\t\tB2[" << i << "] = " << B2[i] << endl; cout << "Press ENTER to continue."; junk = cin.get(); cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; cout << "\n\n\n\n\nHOPE THIS HELPED!\n\n"; cout << "Press ENTER to exit."; junk = cin.get(); return 0; } void arrayByValue(int* arrayPtr) { int i; cout << "---Inside arrayByValue()---\n\n"; cout << "The value pointed to by arrayByValue::arrayPtr is: " << arrayPtr << endl; cout << "It's the same address the main::B points to!\n\n"; cout << "Now lets create an array of size 5, set all it's elements equal to 3,\n"; cout << "and have arrayByValue::arrayPtr point to it.\n"; arrayPtr = new int[5]; cout << "arrayByValue::arrayPtr = " << arrayPtr << endl; for(i = 0; i < 5; i++) { arrayPtr[i] = 3; cout << "arrayByValue::arrayPtr[" << i << "] = " << arrayPtr[i] << endl; } cout << "Note that arrayByValue::arrayPtr now points to a new location in memory.\n\n"; cout << "---Exiting function, arrayByValue()---\n\n"; } void arrayByReference(int* &arrayPointer) { int i; cout << "\n\n---Inside the arrayByReference function.---\n\n"; cout << "The address that, int* arrayPointer points to: " << arrayPointer << endl; cout << "Note that since \"arrayPointer\" is an alias of the int* passed into \n"; cout << "it, it is currently the same address as B, back in main().\n\n"; //arrayByRefference::arrayPointer(aka main::B)---->[][][][][] // main::B2-----^ //create a new array and have the int* point to this array. arrayPointer = new int[5]; cout << "I've just called the \"new\" operator and set \"arrayPointer\" to\n"; cout << "hold the address of the new array.\n"; //now memory looks like this: //arrayByRefference::arrayPointer(aka main::B)---->[][][][][] (new array) // main::B2---->[][][][][] (original array) //initialize the array with all ones and print it to the screen. cout << "The address that int* arrayPointer points to now: " << arrayPointer << endl; cout << "These are the values of the array pointed to by arrayByReference::arrayPointer.\n"; for(i = 0; i < 5; i++) { arrayPointer[i] = 1; //initialize the array with 1 cout << "arrayPointer[" << i << "] = " << arrayPointer[i] << endl; } cout << "\nExiting function, arrayByReference()\n\n"; } int* arrayPassAndReturn(int* arrayPointerPandR) { int i; cout << "\n\n---Inside the arrayPassAndReturn function.---\n\n"; cout << "We passed in an integer pointer. Let's print out what it points to:\n"; cout << "int* arrayPointerPandR: " << arrayPointerPandR << endl; for(i = 0; i < 5; i++) cout << "arrayPointerPandR[" << i << "] = " << arrayPointerPandR[i] << endl; cout << "It points to the same array as B points to in main()\n\n"; cout << "What address does \"arrayPointerPandR\" point to?\t" << arrayPointerPandR << endl; cout << "See? It points to the same address that B does back in main.\n"; cout << "Now, let's use the \"new\" operator to get another array and set\n"; cout << "arrayPointerPandR to point to it.\n"; //create a new iteger array of size 5 and set arrayPointerPandR to point to it. //NOTE: we will lose the ability to get to the original array that was passed in. //BEFORE NEXT LINE OF C++ CODE //arrayPassAndReturn::arrayPointerPandR(aka main::B)---->[1][1][1][1][1] arrayPointerPandR = new int[5]; //Now after creating the new array, memmory looks like this: //arrayPassAndReturn::arrayPointerPandR---->[][][][][] // main::B---->[1][1][1][1][1] //But since B doesn't exist in this scope, the function cannot access the array that contains all 1's //Now let's initialize this array and print it out. for(i = 0; i < 5; i++) { arrayPointerPandR[i] = 2; cout << "arrayPassAndReturn::arrayPointerPandR[" << i << "] = " << arrayPointerPandR[i] << endl; } //returning the integer pointer that points to an array filled with 2's return arrayPointerPandR; }