ENG2139 Lecture 3
ENG2139 Lecture 3
Time Allocation
• Lectures 2 hours/week
• Laboratory/ Tutorials 3 hours/week
5
Memory Address
• In the example from the previous page, the & operator was
used to create a reference variable. But it can also be used
to get the memory address of a variable; which is the
location of where the variable is stored on the computer.
• To access it, use the & operator, and the result will
represent where the variable is stored:
6
string food = "Pizza";
cout << &food; // Outputs 0x6dfed4
7
C++ Pointers
• A pointer is a variable that stores the memory address as its value.
• A pointer variable points to a data type (like int or string) of the same
type, and is created with the * operator. The address of the variable
you're working with is assigned to the pointer:
string food = "Pizza"; // A food variable of type string
string* ptr = &food; // A pointer variable, with the name ptr, that stores the address of food
8
• Create a pointer variable with the name ptr, that
points to a string variable, by using the asterisk sign *
(string* ptr). Note that the type of the pointer has to
match the type of the variable you're working with.
• Use the & operator to store the memory address of
the variable called food, and assign it to the pointer.
• Now, ptr holds the value of food's memory address.
• There are three ways to declare pointer variables, but
the first way is preferred:
9
Get Memory Address and Value
• In the example from the previous page, we used the pointer
variable to get the memory address of a variable (used
together with the & reference operator). However, you can
also use the pointer to get the value of the variable, by using
the * operator (the dereference operator):
string food = "Pizza"; // Variable declaration
string* ptr = &food; // Pointer declaration
// Reference: Output the memory address of food with the pointer (0x6dfed4)
cout << ptr << "\n";
10
Modify the Pointer Value
• You can also change the pointer's value. But note that this will also change the value of the
original variable:
string food = "Pizza";
string* ptr = &food;
// Access the memory address of food and output its value (Pizza)
cout << *ptr << "\n";
11
Pointer Arithmetic
• An array name, without brackets and a subscript,
actually represents the starting address of the
array. This means that an array name is really a
pointer.
• In C++, when you add a value to a pointer, you are
actually adding that value times the size of the data
type being referenced by the pointer.
• This automatic conversion means that an element
in an array can be retrieved by using its subscript or
by adding its subscript to a pointer to the array.
12
• The parentheses are critical when adding values to
pointers. The * operator has precedence over the +
operator, so the expression *number + 1 is not equivalent
to*(number + 1) .
• *number + 1 adds one to the contents of the first
element of the array, while *(number + 1) adds one to
the address in number , then dereferences it.
• Remember that C++ performs no bounds checking with
arrays. When stepping through an array with a pointer,
it’s possible to give the pointer an address outside of the
array.
• The only difference between array names and pointer
variables is that you cannot change the address an array
name points to.
13
• If one address comes before another address in
memory, the first address is considered “less than” the
second. C++’s relational operators may be used to
compare pointer values.
• Comparing two pointers is not the same as comparing
the values the two pointers point to. For example, the
following if statement compares the addresses stored
in the pointer variables ptr1 and ptr2 :
• if (ptr1 < ptr2)
• The following statement, however, compares the
values that ptr1 and ptr2 point to:
• if (*ptr1 < *ptr2)
14
Dynamic Memory Allocation
• To dynamically allocate memory means that a program, while
running, asks the computer to set aside a chunk of unused
memory large enough to hold a variable of a specific data
type.
• you allow the program to create its own variables “on the fly.”
This is called dynamic memory allocation and is only possible
through the use of pointers.
• The way a C++ program requests dynamically allocated
memory is through the new operator. Assume a program has
a pointer to an int defined as
• int *iptr = nullptr;
• Here is an example of how this pointer may be used with the
new operator:
• iptr = new int; 15
• A more practical use of the new operator is to
dynamically create an array.
• iptr = new int[100];
• When memory cannot be dynamically allocated, C++
throws an exception and terminates the program.
• When a program is finished using a dynamically
allocated chunk of memory, it should release it for
future use. The delete operator is used to free
memory that was allocated with new. Here is an
example of how delete is used to free a single variable,
pointed to by iptr :
• delete iptr;
• delete [] iptr;
16
• Only use pointers with delete that were previously
used with new. If you use a pointer with delete that
does not reference dynamically allocated memory,
unexpected problems could result!
• The new operator returns the starting address of the
chunk of memory. It is a good practice to set a pointer
variable to nullptr after using delete on it.
• First, it prevents code from inadvertently using the
pointer to access the area of memory that was freed.
• Second, it prevents errors from occurring if delete is
accidentally called on the pointer again. The delete
operator is designed to have no effect when used on a
null pointer.
17
#include<iostream>
using namespace std;
int main()
{
average = total/numLabs;
20
Call a Function
• Declared functions are not executed immediately. They are "saved for later
use", and will be executed later, when they are called.
• To call a function, write the function's name followed by two parentheses ()
and a semicolon ;
• In the following example, myFunction() is used to print a text (the action),
when it is called:
void myFunction() {
cout << "I just got executed!";
}
int main() {
myFunction(); // call the function
return 0;
}
21
Function Declaration and Definition
• A C++ function consist of two parts:
1. Declaration: the return type, the name of the function,
and parameters (if any)
2. Definition: the body of the function (code to be
executed)
• If a user-defined function, such as myFunction() is
declared after the main() function, an error will occur.
void myFunction();
// The main method
int main() {
myFunction(); // call the function
return 0;
}
// Function definition
void myFunction() {
cout << "I just got executed!";
}
23
C++ Function Parameters
• Information can be passed to functions as a
parameter. Parameters act as variables inside the
function.
• Parameters are specified after the function name,
inside the parentheses. You can add as many
parameters as you want, just separate them with a
comma:
int main() {
myFunction("Liam");
myFunction("Jenny");
myFunction("Anja");
return 0;
}
• When a parameter is passed to the function, it is called an
argument. So, from the example above: fname is a parameter,
while Liam, Jenny and Anja are arguments.
25
Default Parameter Value
• You can also use a default parameter value, by using the equals sign (=).
• If we call the function without an argument, it uses the default value ("Norway"):
26
Multiple Parameters
• Inside the function, you can add as many parameters as you want:
int main() {
myFunction("Liam", 3);
myFunction("Jenny", 14);
myFunction("Anja", 30);
return 0;
}
• Note that when you are working with multiple parameters, the function call must have the
same number of arguments as there are parameters, and the arguments must be passed in
the same order.
27
Return Values
• The void keyword, used in the previous examples, indicates that
the function should not return a value. If you want the function
to return a value, you can use a data type (such as int, string, etc.)
instead of void, and use the return keyword inside the function:
int myFunction(int x) {
return 5 + x;
}
int main() {
cout << myFunction(3);
return 0;
}
// Outputs 8
28
Pass By Reference
• In the examples from the previous page, we used normal
variables when we passed parameters to a function. You can
also pass a reference to the function. This can be useful when
you need to change the value of the arguments:
• When the arguments passed to the functions have been passed
by value.
• This means that when calling a function with parameters, what
we have passed to the function are copies of their values but
never the variables themselves.
• But there might be some cases where you need to manipulate
from inside a function the value of an external variable. For that
purpose we can use arguments passed by reference.
29
void swapNums(int &x, int &y) {
int z = x;
x = y;
y = z;
}
int main() {
int firstNum = 10;
int secondNum = 20;
// Call the function, which will change the values of firstNum and secondNum
swapNums(firstNum, secondNum);
return 0;
}
30
Pass Arrays as Function Parameters
void myFunction(int myNumbers[5]) {
for (int i = 0; i < 5; i++) {
cout << myNumbers[i] << "\n";
}
}
int main() {
int myNumbers[5] = {10, 20, 30, 40, 50};
myFunction(myNumbers);
return 0;
}
• The function (myFunction) takes an array as its parameter (int
myNumbers[5]), and loops through the array elements with the for loop.
• When the function is called inside main(), we pass along the myNumbers
array, which outputs the array elements.
31
• When an array is an argument to a function,
only the address of the first element of the
array is passed, not a copy of the entire array.
(Remember, in C++, an array name without an
index is a pointer to the first element in the
array.)
• There are three ways to declare a parameter
that is to receive an array pointer.
• First, it can be declared as an array of the
same type and size as that used to call the
function.
32
#include <iostream>
using namespace std;
void display(int num[10]);
int main()
{
int t[10],i;
for(i=0; i<10; ++i) t[i]=i;
35
// Pass a pointer to a function.
#include <iostream>
using namespace std;
void f(int *j);
int main()
{
int i;
int *p;
p = &i; // p now points to i
f(p);
cout << i; // i is now 100
return 0;
}
void f(int *j)
{
*j = 100; // var pointed to by j is assigned 100
}
36
Function Overloading
• With function overloading, multiple functions
can have the same name with different
parameters:
int myFunction(int x)
float myFunction(float x)
double myFunction(double x, double y)
37
int plusFuncInt(int x, int y) {
return x + y;
}
int main() {
int myNum1 = plusFuncInt(8, 5);
double myNum2 = plusFuncDouble(4.3, 6.26);
cout << "Int: " << myNum1 << "\n";
cout << "Double: " << myNum2;
return 0;
}
• Instead of defining two functions that should do the same thing, it is better
to overload one.
• In the example below, we overload the plusFunc function to work for both
int and double:
38
int plusFunc(int x, int y) {
return x + y;
}
int main() {
int myNum1 = plusFunc(8, 5);
double myNum2 = plusFunc(4.3, 6.26);
cout << "Int: " << myNum1 << "\n";
cout << "Double: " << myNum2;
return 0;
}
39
Recursion
• Recursion is the technique of making a function call itself. This technique provides a
way to break complicated problems down into simple problems which are easier to
solve.
• Recursion may be a bit difficult to understand. The best way to figure out how it works
is to experiment with it.
int sum(int k) {
if (k > 0) {
return k + sum(k - 1);
} else {
return 0;
}
}
int main() {
int result = sum(10);
cout << result;
return 0;
}
40
Scope Rules of Functions
• The scope rules of a language are the rules
that govern how an object may be accessed by
various parts of your program.
• In other words, the scope rules determine
what code has access to a variable
• There are three types of variables: local
variables, formal parameters, and global
variables.
41
Local Variables
• variables that are declared inside a function are called
local variables.
• In C++, variables can be localized to a block. That is, a
variable can be declared inside any block of code and is
then local to it.
• A local variable can be used only by statements located
within the block in which it is declared.
• the code and data that are defined within one function
cannot interact with the code or data defined in another
function, because the two functions have a different
scope.
42
#include <iostream>
using namespace std;
void f1();
int main()
{
char str[] = "this is str in main()";
cout << str << '\n';
f1();
cout << str << '\n';
return 0;
}
void f1()
{
char str[80];
cout << "Enter something: ";
cin >> str;
cout << str << '\n';
}
43
• When a local variable declared in an inner block
has the same name as a variable declared in an
outer block, the variable declared in the inner
block overrides the one in the outer block,
within the scope of the inner block.
• When a function is called, its local variables are
created, and upon its return, they are destroyed.
This means that local variables cannot retain
their values between calls.
• A local variable can be declared anywhere within
a block, as long as it is declared before it is used.
44
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int main() int main()
{ {
int i, j; cout << "Enter a number: ";
int a; // declare one variable
i = 10;
cin >> a;
j = 100;
cout << "Enter a second number: ";
if(j > 0) {
int b; // declare another variable
int i; // this i is separate from
cin >> b;
outer i
cout << "Product: " << a*b << '\n';
i = j / 2;
return 0;
cout << "inner i: " << i << '\n';
}
}
cout << "outer i: " << i << '\n';
return 0;
}
45
Formal Parameters
• As you know, if a function uses arguments, then it must declare
variables that will accept the values of those arguments.
• These variables are called the formal parameters of the
function.
• Aside from receiving the arguments when a function is called,
formal parameters behave like any other local variables inside
the function.
• The scope of a parameter is local to its function
• You must make sure that the formal parameters you declare
are of the same type as the arguments you will pass to the
function.
46
Global Variables
• Global variables are, in many ways, the opposite of local variables.
They are known throughout the entire program, can be used by any
piece of code, and maintain their values during the entire execution
of the program.
• Therefore, their scope extends to the entire program. You can create
global variables by declaring them outside of any function. Because
they are global, they can be accessed by any expression, regardless
of the function in which the expression is located.
• Global variables are helpful when the same data is used by several
functions in your program, or when a variable must hold its value
throughout the duration of the program.
47
End of Lecture 3
48