0% found this document useful (0 votes)
14 views30 pages

Lecture 9

The document discusses key concepts in algorithms and programming, focusing on references, pass by reference vs value, and scope in C++. It also covers data abstraction with arrays and vectors, including their declaration, initialization, and issues related to indexing. Additionally, it introduces safer access methods and range-based for loops for iterating over arrays.

Uploaded by

ryyjyg9p2r
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views30 pages

Lecture 9

The document discusses key concepts in algorithms and programming, focusing on references, pass by reference vs value, and scope in C++. It also covers data abstraction with arrays and vectors, including their declaration, initialization, and issues related to indexing. Additionally, it introduces safer access methods and range-based for loops for iterating over arrays.

Uploaded by

ryyjyg9p2r
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

Introduction to Algorithms &

Programming
Steve James
Lecture 9
References
• “Reference” is a general concept

int i = 0; int i = 0;
int r = i; int &r = i;
r = 9; //i still 0! r = 9; //i becomes 9 also!

• Can think of a reference as an alternative


name for an object
Pass by reference vs value
#include <iostream>
When we call f
using namespace std;

void f(int x){ 0x…14 0x…fc


cout << "In f, the address of x is " << &x << endl;
x = x + 1;
}
0 0
1
void g(int &x){
cout << "In g, the address of x is " << &x << endl;
x = x + 1;
}

int main(){
int myVar = 0;
cout << "In main, the address of myVar is " << &myVar << endl;
f(myVar);
cout << "Value of myVar is " << myVar << endl;
g(myVar);
cout << "Value of myVar is " << myVar << endl;
return 0;
myVar in main x in f
}

/*
In main, the address of myVar is 0x7ffca4514414
In f, the address of x is 0x7ffca45143fc
Value of myVar is 0
In g, the address of x is 0x7ffca4514414
Value of myVar is 1
*/
Pass by reference vs value
#include <iostream>
When we call g
using namespace std;

void f(int x){ 0x…14


cout << "In f, the address of x is " << &x << endl;
x = x + 1;
}
0
1
void g(int &x){
cout << "In g, the address of x is " << &x << endl;
x = x + 1;
}

int main(){
int myVar = 0;
cout << "In main, the address of myVar is " << &myVar << endl;
f(myVar);
x in g
cout << "Value of myVar is " << myVar << endl;
g(myVar);
cout << "Value of myVar is " << myVar << endl;
return 0;
myVar in main
}

/*
In main, the address of myVar is 0x7ffca4514414
In f, the address of x is 0x7ffca45143fc
Value of myVar is 0
In g, the address of x is 0x7ffca4514414
Value of myVar is 1
*/
Early Abstraction

SCOPE
Scope
• Refers to visibility, accessibility and lifetime of
objects, functions

• e.g. when can we use a variable or function?

• Depends on where declaration occurs


File Scope
• Identifier declared outside any function
definition has file scope
– “global variables”, function definitions/prototypes
outside other functions

• If program consists of multiple files, each has


no knowledge of file-scoped identifiers
outside itself
File Scope
#include <iostream>

using namespace std;

string name;

void greet(){
cout << "Hello " << name << endl;
}

int number;

int f(int x);

int main(){
number = 2;
name = "Bob";
greet();
return 0;
}

int f(int x){


return x * x;
}
Block Scope
• A block is anything within braces: { ... }

• Variables declared in a block only exist within


that block.

• Variables with block scope are known as local


variables
Block Scope
#include <iostream>

using namespace std;

void greet(string name){

cout << "Hello " << name << endl;

int main(){

int x;
cin >> x;

if (x > 0){

string s = "Cassper Nyovest";


greet(s);

}
else{

string s = "Big Zulu";


greet(s);

for (int i = 0; i < 10; ++i){

double q = i + 2;
cout << q << endl;

return 0;
}
Block Scope
• There are also nested blocks e.g. nested if-
statements/loops
• We can define our own blocks simply by using
{ ... } anywhere
• Variables carry into nested scope blocks
• Variable in inner block can have same name as
one in outer block
– Outer block variable will be hidden
Nested Scope
#include <iostream>

using namespace std;

int main(){

{ //scope block
int p;
}

//p does not exist here

{
int x;
{ //nested block
int y; //both x, y exist here
}
//only x exists here
}

for (int i =0; i < 10; ++i){


int outerScope = 10;
for (int j = 0; j < 10; ++j){
int outerScope = 5; //hides variable
cout << outerScope;
}
cout << endl;
}
return 0;
}
Data Abstraction

ARRAYS & VECTORS (PART I)

C++11
Recall Lists
• Python lists
– Store collection of values (of any type)

values = [27, 39, False, "Batman > Superman"]

• C++ equivalents:
– Arrays (fixed-size) and vectors (variable size)
– Must be same (homogeneous) type
– Both arrays and vectors are STL classes
C++11 Arrays
• Need to know the size before program runs!
• Requires C++11
• An array is a contiguous group of memory
locations that all have the same type
• To refer to a particular element in the array,
specify the name of the array and the index of
the particular element
Arrays: Example

d is an int array
d [0] 43 of size 9
d [1] -6
d [2] 55
d [3] 12 The position number is
d [4] 0
d [5] 99 more formally called
d [6] -3 the index or subscript.
d [7] 42
d [8] 99
A subscript must be an
integer (or integer
expression)
Declaring Arrays
• Arrays occupy space in memory
• Specify type and number of elements required
by an array using:
array<type, arraySize> arrayName;
• e.g array<int, 9> d;
• Compiler reserves appropriate amount of
memory based on type and size of array
Arrays in Practice
#include <iostream>
#include <array>
using namespace std;

Use this int main(){


array< int, 5 > d; // d is an array of 5 int values
include! // initialize elements of array d to 0
for (size_t i = 0; i < d.size(); ++i){
d[i] = 0; // set element at location i to 0
}

cout << "Element\tValue" << endl;

// output each array element’s value


for (size_t j = 0; j < d.size(); ++j){
cout << j << "\t\t" << d[j] << endl;
}
size_t is an return(0);
unsigned }

integral type. /*
Output:
Recommended
Element Value
when referring 0 0
to size of array 1 0
2 0
3 0
4 0
*/
Arrays in Practice
#include <iostream>
#include <array>
using namespace std;

int main(){

// Declare and use a list of initializers to initialise d


array< int, 5 > d={ 10, -1, 2, 4, 100 };// d is an array of 5
int values

cout << "Element\tValue" << endl;


Uses an
initializer list to // output each array element’s value
for (size_t j = 0; j < d.size(); ++j){
initialise array cout << j << "\t\t" << d[j] << endl;
}
with 5 value. If return(0);
}
there were
less than 5, the /*
Output:
remaining
Element Value
would be 0 10
initialised to 1 -1
2 2
zero 3 4
4 100
*/
Comparison
• C++ array initialisation

array<int, 5> myArr = {1, 2, 3, 4, 5};

• Python list initialisation

myArr = [1, 2, 3, 4, 5]
Specifying the size
• The array size must be a constant expression
– The compiler must be able to prove the value


• Literals:
array<int, 5> d;

• Variables:


size_t N;
cin >> N;
array<int, N> d;


• Variables:
size_t N = 5;
array<int, N> d;


• Constant expression:
constexpr size_t N = 5;
array<int, N> d;
• C++ provides no automatic array bounds checking to prevent
you from referring to an element that does not exist.
• Thus, an executing program can “walk off” either end of an
array without warning.
• It’s important to ensure that every subscript you use to access
an array element is within the array’s bounds – that is,
greater than or equal to 0 and less than the number of array
elements.
• Allowing programs to read from or write to array elements
outside the bounds of arrays are common security flaws.
• Reading from out-of-bounds array elements can cause a
program to crash or even appear to execute correctly while
using bad data.
• Writing to an out-of-bounds element (known as a buffer
overflow) can corrupt a program’s data in memory, crash a
program and allow attackers to exploit the system and
execute their own code.
• Referring to an element outside the array bounds is an
execution-time logic error. It is not syntax error.
Indexing Issues
• [] operator does not perform any checks
• Attempting to access out-of-bounds index is
undefined behaviour
#include <iostream> #include <iostream>
#include <array> #include <array>
“Inusing
general,namespace
whenever youstd;
encounter undefinedusing
behaviour, anything might
namespace std; happen.
The application
int main(){ may crash, it may freeze, it may int
eject your CD-ROM drive or make
main(){
demons array<int,
come out of your0>nose.
a; It may format your harddrive
array<int, 1> a;
cout << a[0] << endl; cout << a[2] << endl;
It may
} even, if you are really unlucky, appear to } work correctly.”

-Jesper Alf
Segmentation fault (core dumped) 0
Safer Access
• Use at function
– Performs a check before accessing element
– So it’s slower, but provides predictable behaviour
#include <iostream> #include <iostream>
#include <array> #include <array>
using namespace std; using namespace std;
int main(){ int main(){
array<int, 0> a; array<int, 1> a;
cout << a.at(0) << cout << a.at(2) <<
endl; endl;
} }
terminate called after throwing an terminate called after throwing an
instance of ‘std::out_of_range’ instance of ‘std::out_of_range’

• But in general, write code so you never worry


about this happening
Range-based for loop
• Often we want to process all array elements
• The range-based for loop (C++11) allows us
to do this without using a counter
– Avoids possibility of out-of-bounds issues
• If you don’t need access to the subscript, use
this! A type and identifier The array to iterate over

for (<range_variable_declaration> : <expression>){


<statement>;
}
Comparison
• C++ range-based for loop

array<int, 5> myArr = {1, 2, 3, 4, 5};


for (int val : myArr){
cout << val << endl;
}

• Python for loop

myArr = [1, 2, 3, 4, 5]
for val in myArr:
print(val)
Range-based for loop
• The type must be consistent with the array
type
• The identifier represents successive array
element values on successive iterations
• Can use this kind of loop on most STL data
structures (containers)
– array and vector
#include <iostream>
#include <array>
#include <cstdlib>

using namespace std;

int main(){
array<int, 5> d = {1, 2, -1, 3, 5};
cout << "Items before modification: " << endl;
for (int item : d){
cout << item << " ";
}
//multiple elements of d by 3
for (int &itemRef : d){
itemRef *= 3;
}
cout << endl << "Items after modification: " << endl;
for (int item : d){
cout << item << " ";
}
cout << endl;
return 0;
}

/*
Items before modification:
1 2 -1 3 5
Items after modification:
3 6 -3 9 15
*/
Range-based for loop
• Use int reference because d contain int values and we
want to modify each element’s value
• Because itemRef is declared as a reference, any change
you make to itemRef changes the corresponding element
value in the array.
• The range-based for statement can be used in place of the
counter-controlled for statement whenever looping
through an array does not require access to the
element’s subscript.
• However, if a program must use subscripts for some reason
other than simply to loop through an array (e.g., to print
a subscript number next to each array element value),
you should use the counter-controlled for statement.
Summary: Iterating over arrays
for (size_t i = 0; i < arr.size(); ++i){
cout << i << ":\t" << arr[i] << endl;
}

for (int element : arr){


//modifying element will not affect the array
cout << element << endl;
}

for (int &element : arr){


//modifying element will affect the array
cout << element << endl;
}

You might also like