KEMBAR78
Lecture 10 | PDF | Variable (Computer Science) | Parameter (Computer Programming)
0% found this document useful (0 votes)
12 views45 pages

Lecture 10

The document provides an overview of arrays and vectors in C++ and Python, highlighting their declaration, initialization, and iteration methods. It covers the differences between fixed-size arrays and dynamic vectors, as well as memory allocation and pointer usage in C++. Additionally, it discusses operations such as sorting and searching within arrays and vectors.

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)
12 views45 pages

Lecture 10

The document provides an overview of arrays and vectors in C++ and Python, highlighting their declaration, initialization, and iteration methods. It covers the differences between fixed-size arrays and dynamic vectors, as well as memory allocation and pointer usage in C++. Additionally, it discusses operations such as sorting and searching within arrays and vectors.

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/ 45

Introduction to Algorithms &

Programming
Steve James
Lecture 10
Recap
• 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
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
Comparison
• C++ array initialisation

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

• Python list initialisation

myArr = [1, 2, 3, 4, 5]
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)
Data Abstraction

ARRAYS & VECTORS (PART I)

C++11
#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;
}
Multidimensional arrays
• Array declaration:
– array<type, size> name;
• Type can be int, string, double,...
• But arrays are also types
• So we can have arrays of arrays
Multidimensional arrays
• Multidimensional arrays: those with 2 or more
dimensions
• 2D arrays can be used to represent
tables/matrices
– Data arranged in rows and columns
• We must specify two subscripts. By
convention:
– first is the row,
– second is the column
2D arrays
arr is a two-dimensional array

It contains three rows and four columns, so it’s called a 3-by-4 array

Column 0 Column 1 Column 2 Column 3


Row 0 arr[0][0] arr[0][1] arr[0][2] arr[0][3]
Row 1 arr[1][0] arr[1][1] arr[1][2] arr[1][3]
Row 2 arr[2][0] arr[2][1] arr[2][2] arr[2][3]

array name column subscript

row subscript
3 × 4 Matrix
array< TYPE , 3> matrix;

array< array<int, 4> , 3> matrix;


#include <array>
#include <iostream>
To process the elements of a two-dimensional array, we
using namespace std;
use a nested loop in which the outer loop iterates through
//remember const! the rows and the inner loop iterates through the columns
const size_t ROWS = 2;
const size_t COLS = 3; of a given row
//why pass by reference?
void printMatrix(const array<array<int, COLS>, ROWS> &matrix){
//for each row
for (size_t row = 0; row < matrix.size(); ++row){
//for each element in the current row
for (size_t col = 0; col < matrix[row].size(); ++col){
cout << matrix[row][col] << ' ';
}
cout << endl;
}
} Type of array is array<int, COLS>
int main(){
array<array<int, COLS>, ROWS> matrix = {
1, 2, 3,
4, 5, 6
};
cout << "Matrix: " <<endl; Initialising 2D arrays
printMatrix(matrix);
array<array<int, COLS>, ROWS> matrix2 = {
7, 8, 9
};
cout << endl << "Matrix2: " <<endl;
printMatrix(matrix2);
return 0;
}

/*Output:
Matrix:
1 2 3
4 5 6

Matrix2:
7 8 9
0 0 0 */
Side note: iteration
• Quicker way of iterating over 2D array with
range-based for loop
void printMatrix(const array<array<int, COLS>, ROWS> &matrix){
//for each row
for (size_t row = 0; row < matrix.size(); ++row){
//for each element in the current row
for (size_t col = 0; col < matrix[row].size(); ++col){
cout << matrix[row][col] << ' ';
}
cout << endl;
}
}

VS
void printMatrix(const array<array<int, COLS>, ROWS> &matrix){
for (auto row : matrix){ The C++11 auto
//auto infers that row is of type array<int, COLS>
for (auto element : row){ keyword tells the
cout << element << ' '; compiler to infer a
}
cout << endl; variable’s data type based
}
} on its initializer value.
Some array operations
• The STL provides functions that can be applied
to arrays (and vectors)
– #include <algorithm>

• A full list of functions is listed here


– http://www.cplusplus.com/reference/algorithm/
Sorting
• Sort data: place elements into ascending or
descending order
#include <iostream>
#include <array>
#include <string>
#include <algorithm>

using namespace std;

int main(){
array<string, 4> colours = {"blue", "black", "red", "green"};
for (string colour : colours){
cout << colour << ' ';
}
cout << endl;
sort(colours.begin(), colours.end()); begin() and end()
for (string colour : colours){
cout << colour << ' '; refer to the range to
}
return 0;
sort over.
}

/*
Output:
blue black red green
black blue green red
*/
Search (I)
• Determine whether an array contains a certain
key value
• Perform a binary_search for the key
– Pro: super efficient
– Con: array must be sorted first!
Binary Search Example
#include <iostream>
#include <array>
#include <string>
#include <algorithm>

using namespace std;

int main(){
array<string, 4> colours = {"blue", "black", "red", "green"};
sort(colours.begin(), colours.end()); //must be sorted
string key = "black";
bool found = binary_search(colours.begin(), colours.end(), key); //look for
black
if (found){
cout << "We found the key 'black'" << endl;
}
return 0;
}
Search (II)
• Determine the number of elements equal to
something
– Use count function
#include <iostream>
#include <array>
#include <algorithm>

using namespace std;

int main(){
array<int, 5> nums = {1, 2, 3, 100, 2};
//counting number of twos
int numOccurrences = count(nums.begin(), nums.end(), 2);
cout << 2 << " appeared " << numOccurrences << " times" << endl;
return 0;
}

/*
2 appeared 2 times
*/
Search (III)
• Determine the number of elements satisfying
some condition
– Use count_if function
#include <iostream>
#include <array>
#include <algorithm>

using namespace std;

bool isEven(int x){


return x %2 == 0;
}

int main(){
array<int, 5> nums = {1, 2, 3, 100, 2};
//counting number of even numbers
int numOccurrences = count_if(nums.begin(), nums.end(), isEven);
cout << numOccurrences << " numbers are even" << endl;
return 0;
}

/*
3 numbers are even
*/
Vectors
• Arrays are great, but…
– Need to know the size up front 
• Enter the vector
– #include <vector>
• Like arrays, but support dynamic resizing
– All STL functions that work on arrays work on
vectors
• Question: Why would we even use arrays
then?
Creating vectors
• Compare arrays:
– array<type, size> name;
• With vectors:
– vector<type> name;

• Different options for declaring vectors


vector<int> v1 // vector of size 0
vector<int> v2(17); // 17 elements, each with value 0
vector<string> v3(17, "Bob"); // 17 elements, each with value Bob
vector<int> v4{17}; // 1 element of value 17
Some Vector Functions
Function Effect Usage
resize Changes the vector<int> vec {1, 2, 3};
number of vec.resize(5);
elements stored //now vec = {1,2,3,0,0}
vec.resize(1);
//now vec = {1}

push_back Adds an element vector<int> vec {1, 2, 3};


to the end vec.push_back(4);
//now vec = {1,2,3,4}

clear Removes all vector<int> vec {1, 2, 3};


elements from vec.clear();
the vector //now vec = {}

reserve Reserve memory vector<int> vec;


for the vector vec.reserve(100);
//now vec = {}, can add many ints
before background resizing needed
Vector Operations
• Everything you can do with arrays, can do with
vectors:
– size() function
– Iteration
– Multidimensional vectors
– Accessing with [] operator
Low-level C++

MEMORY ALLOCATION & LAYOUT


Aims
• Understand
– how C++ organises memory
– when to use which type
– how things like vector work behind the scenes
• Extremely important for low-level languages
(like C)
• Warning: use modern C++11 constructs to
avoid all this unpleasantness in practice
Then why?
• What is the plural of octopus?

• Octopus is not Latin, but from Greek oktopous

• Therefore, its plural is not octopi, but


octopodes
Memory Layout
• Local variables reside on the stack
– Automatic allocation Code

• Global variables are stored in static


data Static data
Heap/Free store
• Code section stores the executable
code

• Heap is a bunch of extra memory Stack


assigned to us
– Dynamic allocation
Stack
• The stack is used to store
– the return addresses at function calls
– arguments passed to the functions
– local variables for functions
– CPU state
• Every time a function is called, a new stack
frame is placed on the stack
• When the function ends, the stack frame is
removed
Stack Frame

Optional
Last auto variable

First auto variable

Return address
Optional

First parameter

Last parameter
Optional

Return space
Stack Frames
#include <iostream>

using namespace std;


y: 4 bytes

Stack frame for square()


int square(int x){
int y = x * x;
cout << y << endl; 0x643c
return y;
} x: 4 bytesz: 4 bytes

Stack frame for main()


x: 4 bytes
int main(){ 4 bytes
int x = 2; 0x23242f
int z = square(x);
return 0;
}

4 bytes
Stack Issues
• Compiler automatically manages stack for us
• Must know how much memory to allocate
beforehand (sound familiar?)
• Stack size is small
– Cuts down on overhead
– But may run out of memory (try create an 100m
element arrray!)
• This is where the heap comes in
• But first…
Low-level C++

POINTERS
Note
• What we’re about to look at are called raw
pointers

• Where possible, avoid these in your code

• Use smart pointers (C++11) instead


Pointer
• A pointer is a variable that holds the memory
address of another variable
• So variable name refers to a value, while a
pointer indirectly refers to a value
– Indirection: referencing a value through a pointer

y x
int x = 7;
int *y = &x; 7
References vs Pointers
• Pointers can be reassigned; references cannot,
and must be initialised
• Can have pointers to pointers; cannot have
references to references
• Pointers can have a “null” value; references
cannot
• Pointers can be used for iteration
• References are safer and cleaner than pointers
– Prefer references where possible
Declaring Pointers
• int *ptr;
– the variable ptr is declared to be a pointer to an int
value
– any variable declared as a pointer must be preceded
by an asterisk ( * )
• When * appears in a declaration, it is not an
operator; rather, it indicates that the variable is a
pointer
• Pointers can point to objects of any type
• Question: How many bytes does a pointer take
up?
Declaring Pointers
• double *ptr; • A pointer to a double
• int **ptr; • A pointer to an
integer pointer

• const int * ptr;


• int * const ptr;
• const int * const ptr;

READ FROM RIGHT TO LEFT


Initialising Pointers
• Pointers should be given the memory address of
the variable they refer to
• Or, they may be set to “point to nothing”
– This is known as a “null pointer”
• In C++11, use the nullptr keyword:
– int *ptr = nullptr;
• Prior to C++11, 0 or NULL was used instead
– int *ptr = 0;
– int *ptr = NULL;
Pointer Operators
• The address operator (&) gets the address of
its operand
int x = 10; //declare variable x
int *xPtr = nullptr; //declare null pointer xPtr
//... a bit later in the code
xPtr = &x; //make xPtr point to x

x xPtr

10 0xbfb08e58
0xbfb08e58 0xbfb08e5c
Pointer Operators
• The operand of the address operator must be
an lvalue
– the address operator cannot be applied to
constants or to expressions that result in
temporary values (like the results of calculations).

int *xPtr = &(12 * 2); //Are you MAD?! No way, Jose!


Pointer Operators
• The indirection/dereferencing operator (*)
operator returns an lvalue representing the
object to which its pointer operand points.
– This is operation is called dereferencing a pointer.
int x = 10;
int *xPtr = &x;
/* Output
cout << "Address of x: " << &x << endl;
Address of x: 0x7fffedda4f04
cout << "Value of xPtr: " << xPtr << endl;
cout << "Value of x: " << x << endl; Value of xPtr: 0x7fffedda4f04
cout << "Value of *xPtr: " << *xPtr << endl; Value of x: 10
x = 0; //change x's value Value of *xPtr: 10
cout << "Value of *xPtr: " << *xPtr << endl; Value of *xPtr: 0
*xPtr = 42; //change x through the pointer Value of x: 42
cout << "Value of x: " << x << endl; */
Passing Pointers
• Recall: pass-by-reference and pass-by-value
• We can pass a pointer (by value)
• But because it points to an object, we can
modify the object in our function
• Just like pass-by-reference!
– Avoids overhead of passing large objects
#include <iostream>

using namespace std;

//by value
int cubeByVal(int x){
int t = x * x * x;
return t;
}

//by reference
void cubeByRef(int &x){
x = x * x * x;
}

//by pointer
void cubeByPtr(int *x){
*x = (*x) * (*x) * (*x); Dereferencing
}

int main(){
int number = 2;
cubeByVal(number);
cout << "After pass-by-value: " << number << endl;
cubeByRef(number);
cout << "After pass-by-reference: " << number << endl;
cubeByPtr(&number);
cout << "After pass-by-pointer-value: " << number << endl;
Address operator
}

/**
After pass-by-value: 2
After pass-by-reference: 8
After pass-by-pointer-value: 512
**/

You might also like