Variables, Functions & Parameter Passing CSci 588 Fall 2013 All material not from online sources copyright © Travis Desell, 2011.

Slides:



Advertisements
Similar presentations
Pass by Value. COMP104 Pass by Value / Slide 2 Passing Parameters by Value * A function returns a single result (assuming the function is not a void function)
Advertisements

What is a pointer? First of all, it is a variable, just like other variables you studied So it has type, storage etc. Difference: it can only store the.
Ch. 8 Functions.
CSE 332: C++ exceptions Overview of C++ Exceptions Normal program control flow is halted –At the point where an exception is thrown The program call stack.
Pointers Typedef Pointer Arithmetic Pointers and Arrays.
1 Lecture 18:User-Definded function II(cont.) Introduction to Computer Science Spring 2006.
Pointers and dynamic objects COMP171 Fall Pointers and dynamic objects/ Slide 2 Topics * Pointers n Memory addresses n Declaration n Dereferencing.
1 Chapter 7 Functions Dale/Weems/Headington. 2 Functions l Control structures l every C++ program must have a function called main l program execution.
Review on pointers and dynamic objects. Memory Management  Static Memory Allocation  Memory is allocated at compiling time  Dynamic Memory  Memory.
1 Pointers, Dynamic Data, and Reference Types Review on Pointers Reference Variables Dynamic Memory Allocation –The new operator –The delete operator –Dynamic.
1. 2 FUNCTION INLINE FUNCTION DIFFERENCE BETWEEN FUNCTION AND INLINE FUNCTION CONCLUSION 3.
Overview scope - determines when an identifier can be referenced in a program storage class - determines the period of time during which that identifier.
Functions Modules in C++ are called functions and classes
Computer Science 1620 Reference Parameters. Parameters – Pass by Value recall that the parameter of a function is assigned the value of its corresponding.
Command line arguments. – main can take two arguments conventionally called argc and argv. – Information regarding command line arguments are passed to.
Chapter 7 Functions.
VARIABLES, TYPES, INPUT/OUTPUT, ASSIGNMENT OPERATION Shieu-Hong Lin MATH/CS Department Chapel.
CSE 332: C++ functions Review: What = and & Mean In C++ the = symbol means either initialization or assignment –If it’s used with a type declaration, it.
Modular Programming Chapter Value and Reference Parameters computeSumAve (x, y, sum, mean) ACTUALFORMAL xnum1(input) ynum2(input) sumsum(output)
C++ function call by value The call by value method of passing arguments to a function copies the actual value of an argument into the formal parameter.
COMPUTER PROGRAMMING. Functions What is a function? A function is a group of statements that is executed when it is called from some point of the program.
Week 6 - Wednesday.  What did we talk about last time?  Exam 1!  And before that…  Review!  And before that…  Arrays and strings.
ITEC 320 C++ Examples.
Functions Modules in C++ are called functions and classes Functions are block of code separated from main() which do a certain task every C++ program must.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Command Line Arguments.
C++ Memory Overview 4 major memory segments Key differences from Java
Object-Oriented Programming in C++
Dynamic memory allocation and Pointers Lecture 4.
Current Assignments Start Reading Chapter 6 Project 3 – Due Thursday, July 24 Contact List Program Homework 6 – Due Sunday, July 20 First part easy true/false.
COMPUTER PROGRAMMING. Functions’ review What is a function? A function is a group of statements that is executed when it is called from some point of.
Tracing through E01, question 9 – step 1 // p02.cc P. Conrad, for CISC181 07S // Exam question for E01 #include using namespace std; void mysteryFunction(int.
1 Command-Line Processing In many operating systems, command-line options are allowed to input parameters to the program SomeProgram Param1 Param2 Param3.
CPS4200 Unix Systems Programming Chapter 2. Programs, Processes and Threads A program is a prepared sequence of instructions to accomplish a defined task.
Week 2. Functions: int max3(int num1, int num2, int num3) {int result; result = max(max(num1,num2),num3); return result; } //max3.
1 Workin’ with Pointas An exercise in destroying your computer.
1 Chapter 2 C++ Syntax and Semantics, and the Program Development Process.
CSE 232: C++ memory management Overview of Arrays Arrays are the simplest kind of data structure –One item right after another in memory (“contiguous range”
Objective: Students will be able to: Declare and use variables Input integers.
© M. Gross, ETH Zürich, 2014 Informatik I für D-MAVT (FS 2014) Exercise 4 – Logical Operators & Branching.
CS415 C++ Programming Takamitsu Kawai x4212 G11 CERC building WV Virtual Environments Lab West Virginia University.
Exceptions in C++. Exceptions  Exceptions provide a way to handle the errors generated by our programs by transferring control to functions called handlers.
CSE 332: C++ Statements C++ Statements In C++ statements are basic units of execution –Each ends with ; (can use expressions to compute values) –Statements.
Functions Illustration of: Pass by value, reference Scope Allocation Reference: See your CS115/215 textbook.
System Programming Practical Session 7 C++ Memory Handling.
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Recursion.
Cop3530sp12. Parameter passing call by value- appropriate for small objects that should not be altered by the function call by constant reference- appropriate.
CSE 332: C++ pointers, arrays, and references Overview of Pointers and References Often need to refer to another object –Without making a copy of the object.
CS162 - Topic #6 Lecture: Pointers and Dynamic Memory –Review –Dynamically allocating structures –Combining the notion of classes and pointers –Destructors.
C++ Namespaces, Exceptions CSci 588: Data Structures, Algorithms and Software Design All material not from online sources copyright © Travis Desell, 2011.
C++ Functions A bit of review (things we’ve covered so far)
C Tutorial - Pointers CS 537 – Introduction to Operating Systems.
C++ REVIEW – TEMPLATES. GENERIC PROGRAMMING Programming/developing algorithms with the abstraction of types Algorithms/data is expressed “without type”
CSE 332: C++ Exceptions Motivation for C++ Exceptions Void Number:: operator/= (const double denom) { if (denom == 0.0) { // what to do here? } m_value.
Overview 4 major memory segments Key differences from Java stack
Motivation and Overview
Command Line Arguments
Chapter 5 Function Basics
Student Book An Introduction
Variables with Memory Diagram
Overview 4 major memory segments Key differences from Java stack
Chapter 5 Function Basics
Pointers, Dynamic Data, and Reference Types
Pointers & Functions.
Functions Pass By Value Pass by Reference
Pass by Reference.
Chapter 9: Pointers and String
Pointers and dynamic objects
Pointers & Functions.
Functions Reasons Concepts Passing arguments to a function
Presentation transcript:

Variables, Functions & Parameter Passing CSci 588 Fall 2013 All material not from online sources copyright © Travis Desell, 2011

Variables Variables consist of a name/type pair. The name can be anything (starting with ‘_’ or a letter), while the type refers to some kind of data.

Variables Within a function, variables reside in a set of registers for that function. These are temporary spots in memory (think on CPU memory), and each function will have it’s own set of registers. When you create an array or an object with the ‘new’ keyword, it actually allocates persistent memory (think RAM) that doesn’t go away until you delete it with the ‘delete’ keyword.

A Simple Example

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; }

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example Registers: c++ will create an array of references to arrays of characters (an array of characters is an old style c string). These are in memory. c++ also makes two registers, an int which we’re calling ‘argc’ and a pointer to the array of pointers to arrays of characters which we’re calling ‘argv’. Memory: argv pointer to char array argv[0]argv[1]argv[2]... argc some number argv pointer to memory argv[0] some char argv[0][0]argv[0][1]argv[0][2]...

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example Registers: ‘argc’ is short for argument count (it’s the number of command line arguments), and ‘argv’ is short for argument vector (it’s the number of arguments passed by the command line). Memory: argv pointer to char array argv[0]argv[1]argv[2]... argc some number argv pointer to memory argv[0] some char argv[0][0]argv[0][1]argv[0][2]...

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example Registers: Note that there will be an array in memory for each command line argument, argv[0], argv[1], argv[2],... and so on. But since we’re not using these I’m going to remove them from the rest of the slides. Memory: argv pointer to char array argv[0]argv[1]argv[2]... argc some number argv pointer to memory argv[0] some char argv[0][0]argv[0][1]argv[0][2]...

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example xy Registers: This statement will create two registers with enough space in each for an int. Memory: argc some number argv pointer to memory

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 5 y Registers:Memory: argc some number argv pointer to memory This will set the data at the register for ‘x’ to 5.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 5 y 3 Registers:Memory: argc some number argv pointer to memory This will set the data at the register for ‘y’ to 3.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 5 y 3 Registers:Memory: argc some number argv pointer to memory temp 5 This will create the register for the ‘temp’ variable and assign it’s data to the data in the ‘x’ variables register in one line.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 5 y 3 Registers:Memory: argc some number argv pointer to memory temp 5 Note that the data at the x register does not change, it’s only copied over to the temp register.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 3 y 3 Registers:Memory: argc some number argv pointer to memory temp 5 This will set the data at the ‘x’ register to the data at the ‘y’ register. Again, the data at the ‘y’ register does not change, nor does the data at the ‘temp’ register.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 3 y 5 Registers:Memory: argc some number argv pointer to memory temp 5 This will set the data at the ‘y’ register to the data at the ‘temp’ register. ‘temp’ and ‘x’ don’t change, for the same reasons as before. The data is just copied into the register.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example x 3 y 5 Registers:Memory: argc some number argv pointer to memory temp 5 When the program finishes, the data for the ‘x’ and ‘y’ variables has been swapped.

#include int main(int argc, char **argv) { int x, y; x = 5; y = 3; int temp = x; x = y; y = temp; } A Simple Example Registers:Memory: After the function completes, the registers are removed. Regsiters only live for the duration of the function they are created in, and can only be accessed from within the function they were created in.

An Example with Methods

01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Call Stack: Remember, the program always starts with the main function. Also, we’ll be ignoring argc and argv again (since we aren’t using them). Registers for ‘main’:

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Call Stack: This line does the same thing as the first three lines of the previous program’s main method. It creates two variables ‘x’ and ‘y’, along with a register for each large enough to hold an int value. It then sets the value at x’s register to 5 and y’s register to 3. x 5 y 3 Registers for ‘main’:

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Now things get tricky. We’ll make another register called largest, again with enough space for an int. x 5 y 3 largest ?

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: But what do we set largest to? Now we need to deal with the call stack. The flow of the program leaves the main function and goes into the max function. All the registers of main are put on hold, waiting for the max function to return. x 5 y 3 largest ?

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: So we put line 14 of main on the call stack, and then the flow of our program moves into the max function. x 5 y 3 largest ? main : 14

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: When the flow of the program goes into the new function, the new function has registers made for each of it’s arguments, n1 and n2 (just like in the previous example c++ made registers for argc and argv). x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 ? n2 ?

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Note that the type of the ‘x’ variable is an int, and the type of ‘n1’ is also an int -- these parameters match. The type of ‘y’ is an int, and the type of ‘n2’ is also an int, so they match as well. When you call a function (the function is called on line 14), the types arguments you pass into it must match the types in the function declaration (the function is declared on line 4). x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 ? n2 ?

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: When you call the function, it sets the values of the registers of the variables in the function declaration to the values of the variables passed into the function. In this case, the value of x gets copied into n1’s register, and the value of y gets copied into n2’s register. x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 5 n2 3

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Now the program has finished all the initialization to call the max function and the program starts going from line 04, the beginning of the max function. x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 5 n2 3 max : 04

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: This if statement now compares the values of n1 and n2. If n1 > n2 (n1 is greater than n2), the flow of the program moves into the proceeding block, if not, it moves into the block of code after the else statement. (A block of code is the code between {}s). x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 5 n2 3 max : 05

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Since n1 > n2, we move to line 06 (if it had not been, we would have moved to line 08). x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 5 n2 3 max : 05

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Now we reach a return statement. A return statement automatically leaves a function, and if a register was waiting for the value of that function; (in this case, the ‘largest’ register was), that register gets set to the value after the return. Note that the return type of a function(max returns an int, as declared on line 4), must match the data type of the register it the return value of the function is being assigned to. x 5 y 3 largest ? main : 14 Registers for ‘max’: n1 5 n2 3 max : 06

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: So this statement returns the value of the ‘n1’ register, and assigns the value of the ‘largest’ register to it. The flow of the program immediately leaves the max function, it is removed from the call stack and it’s registers are removed as well. x 5 y 3 largest 5 main : 14 Registers for ‘max’: n1 5 n2 3 max : 06

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: So this statement returns the value of the ‘n1’ register, and assigns the value of the ‘largest’ register to it. The flow of the program immediately leaves the max function, it is removed from the call stack and it’s registers are removed as well. x 5 y 3 largest 5 main : 14

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: We now go back to line 14 of the main function (which was saved on the call stack), and as the register for largest has been set we can continue in the main function. x 5 y 3 largest 5 main : 14

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: Line 15 will print out the value at the largest register to the screen. x 5 y 3 largest 5 main : 15

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Registers for ‘main’:Call Stack: When the main function completes, it is popped off the call stack, the registers are removed and the program is over. x 5 y 3 largest 5 main : 15

An Example with Methods 01 #include 02 using namespace std; int max(int n1, int n2) { 05 if (n1 > n2) { 06 return n1; 07 } else { 08 return n2; 09 } 10 } int main(int argc, char **argv) { 13 int x = 5, y = 3; 14 int largest = max(x, y); 15 cout << largest << endl; 16 } Call Stack: When the main function completes, it is popped off the call stack, the registers are removed and the program is over.

Another Example with Methods

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Again, your program always starts at the main function. And again, we’re going to ignore the registers and memory for argc and argv because we’re not using them. main : 13

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Just as before, we make two registers, one for ‘x’ and one for ‘y’, each large enough to hold an int. The x register is assigned a 5 and the y register is assigned a 3. x 5 y 3 main : 14

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 15 swap_right(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 } Registers for ‘main’:Call Stack: We don’t have a register waiting for a return value, but we’re still calling the function. Just like with the max function, we add swap_wrong to the call stack, create the registers for it’s arguments (n1 and n2) and assign their values to x and y. x 5 y 3 main : 15

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: We don’t have a register waiting for a return value, but we’re still calling the function. Just like with the max function, we add swap_wrong to the call stack, create the registers for it’s arguments (n1 and n2) and assign their values to x and y. x 5 y 3 main : 15 swap_wrong : 03

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: We don’t have a register waiting for a return value, but we’re still calling the function. Just like with the max function, we add swap_wrong to the call stack, create the registers for it’s arguments (n1 and n2) and assign their values to x and y. x 5 y 3 main : 15 swap_wrong : 03 Registers for ‘swap_wrong’: n1 5 n2 3

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Now execution continues from line 03. x 5 y 3 main : 15 swap_wrong : 03 Registers for ‘swap_wrong’: n1 5 n2 3

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Line 04 creates a new register for temp, and copies the data from n1 into that register. x 5 y 3 main : 15 swap_wrong : 04 Registers for ‘swap_wrong’: n1 5 n2 3 temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Line 05 copies the value from the n2 register into the n1 register. x 5 y 3 main : 15 swap_wrong : 04 Registers for ‘swap_wrong’: n1 3 n2 3 temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Line 06 copies the value from the temp register into the n2 register. x 5 y 3 main : 15 swap_wrong : 04 Registers for ‘swap_wrong’: n1 3 n2 5 temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: The function finishes on line 07, which removes all the registers for swap_wrong and brings us back into the main method where we left off. x 5 y 3 main : 15 swap_wrong : 04 Registers for ‘swap_wrong’: n1 3 n2 5 temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: The function finishes on line 07, which removes all the registers for swap_wrong and brings us back into the main method where we left off. x 5 y 3 main : 15

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Note that now we have a problem, we changed the values of the registers for the swap_wrong function, but nothing changed with the registers for our main function! The swap_wrong function doesn’t work! x 5 y 3 main : 15

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: When we print out x and y, it still prints out 5 and 3, because the x and y registers of the main function never got changed. Luckily c++ has a solution to this problem (although some computer scientists may argue this is a bad thing). x 5 y 3 main : 16

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: If you put a & before a parameter in a function, as in the swap_right function, the parameters to the function are passed by reference (instead of by value). x 5 y 3 main : 17

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: This means, when the flow of our program goes into the swap_right function, the swap_right function is using the same registers as were passed into the function. n1 and x are the same, and n2 and y are the same. x 5 y 3 main : 17

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: This means, when the flow of our program goes into the swap_right function, the swap_right function is using the same registers as were passed into the function. n1 and x are the same, and n2 and y are the same. x 5 y 3 main : 17 swap_right : 08 n1 reference to x n2 reference to y Registers for ‘swap_right’:

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Now the program keeps going from the beginning of the swap_right function. x 5 y 3 main : 17 swap_right : 08 n1 reference to x n2 reference to y Registers for ‘swap_right’:

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: We create a new register called ‘temp’ and assign it to the value of n1 -- which is the value at the x register. x 5 y 3 main : 17 swap_right : 09 n1 reference to x n2 reference to y Registers for ‘swap_right’: temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Now when we assign n2 to n1, it is copying the value from the y register into the x register; because n2 is a reference to y and n1 is a reference to x. x 3 y 3 main : 17 swap_right : 10 n1 reference to x n2 reference to y Registers for ‘swap_right’: temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: And when we assign the value of temp to n2, we’re actually setting the value at the y register, because n2 is a reference to y. x 3 y 5 main : 17 swap_right : 11 n1 reference to x n2 reference to y Registers for ‘swap_right’: temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: When the function finishes, the registers used by swap right are removed -- in this case the two references to x and y (n1 and n2, respectively) as well as temp. x 3 y 5 main : 17 swap_right : 12 n1 reference to x n2 reference to y Registers for ‘swap_right’: temp 5

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: When the function finishes, the registers used by swap right are removed -- in this case the two references to x and y (n1 and n2, respectively) as well as temp. x 3 y 5 main : 17 swap_right : 12

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Following this, we pop the function off the call stack and go back to where we left off. x 3 y 5 main : 17

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Following this, we pop the function off the call stack and go back to where we left off. x 3 y 5 main : 17

Call by Reference 01 #include 02 using namespace std; 03 void swap_wrong(int n1, int n2) { 04 int temp = n1; 05 n1 = n2; 06 n2 = temp; 07 } 08 void swap_right(int &n1, int &n2) { 09 int temp = n1; 10 n1 = n2; 11 n2 = temp; 12 } 13 int main(int argc, char **argv) { 14 int x = 5, y = 3; 15 swap_wrong(x, y); 16 cout << “x: ” << x << “, y: “ << y << endl; 17 swap_right(x, y); 18 cout << “x: ” << x << “, y: “ << y << endl; 19 } Registers for ‘main’:Call Stack: Now when we print out the values of x and y, they are actually swapped. This is because the parameters passed to swap_right were call by reference (because of the &s); unlike in swap_wrong, which is call by value (the default case). x 3 y 5 main : 18