Lecture Notes 03 (CSI2372 - Advanced Programming Concepts With C++)
Lecture Notes 03 (CSI2372 - Advanced Programming Concepts With C++)
Course Overview:
Advanced Programming Concepts with C++ (CSI2372) is designed to expand your programming skills and deepen your
understanding of C++ and its applications. Throughout the course, we will explore various advanced programming
concepts, ranging from differences between C++ and Java programming to numerical computation and interfacing with
hardware.
Teaching Assistant:
1. Bhattacharjee/Mayukh, email: [email protected]
2. Dai/Lansu, email: [email protected]
3. Emami Afshar/Bahar, email: [email protected]
4. Khare/Akshat, email: [email protected]
5. Kumar/Preyank, email: [email protected]
6. Yathirajulu/Ruchitha, email: [email protected]
7. Keswani /Yash, email: [email protected]
1
CSI2372 - Advanced Programming Concepts with C++
Course Outline:
2
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
• Session 2: Pointers, Memory Management, and Efficiency
• Pointer Arithmetic and Advanced Data Structures
• Function Pointers and Callbacks
• Pointer to Pointers and Pointers to Functions
• Pointer Safety and Best Practices
• Low-Level Memory Access and Assembly
3
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
4
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Understanding pointer arithmetic.
❑ Pointer arithmetic is a fundamental concept in C and C++ that allows you to perform arithmetic
operations on pointers to navigate and manipulate memory. It's an essential skill for low-level
programming, data manipulation, and working with arrays and data structures. Pointer arithmetic is
closely related to the size of the data type being pointed to.
5
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Understanding pointer arithmetic.
int numbers[] = {10, 20, 30, 40, 50};// this line is from previous slide to only show the array
ptr = ptr + 2; // continuation of the previous code lines
// Move 'ptr' two elements forward. ptr points to the third 3rd element (30) of the array.
int thirdElement = *ptr;
// 'thirdElement' now contains the value 30. By dereferencing ptr, you retrieve the value that ptr points to.
int* anotherPtr = numbers + 4;
// 'anotherPtr' points to the 5th element.
int elementsBetween = anotherPtr - ptr;
// Calculates the number of elements between 'ptr' and 'anotherPtr’.
// In this case, elementsBetween will be 5-3 = 2 because there are two elements between the third and fifth
elements in the array.
6
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Working with multidimensional arrays using pointers.
❑ Multidimensional arrays are arrays of arrays, where data is organized in a tabular form with rows and
columns. In C and C++, multidimensional arrays are typically stored in memory as contiguous blocks
of data. Pointers provide a way to navigate this memory efficiently. When you declare a pointer to a
multidimensional array, it allows you to access individual elements and traverse the array by
adjusting the pointer position. Keep it in mind that rows and columns starts from 0, 1, and 2…
int matrix[4][3] = { {11, 12, 13}, {14, 15, 16}, {17, 18, 19}, {110, 111, 112} };
int(*ptr)[3] = &matrix[1]; // Points to the second row (index 1) of matrix and the pointer have access on 3 arrays
7
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Working with multidimensional arrays using pointers.
int main() {
int matrix[4][3] = { {11, 12, 13}, {14, 15, 16}, {17, 18, 19}, {110, 111, 112} };
// Access the values at the addresses of individual elements in the second row
int value_1 = (*ptr)[0]; // int address_1 = &(*ptr)[0]; for address of this pointer
int value_2 = (*ptr)[1]; // int address_2 = &(*ptr)[1]; for address of this pointer
int value_3 = (*ptr)[2]; // int address_3 = &(*ptr)[2]; for address of this pointer
int main() {
int matrix[4][3] = { {11, 12, 13}, {14, 15, 16}, {17, 18, 19}, {110, 111, 112} };
9
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Working with multidimensional arrays using pointers.
You can use nested loops and pointers to traverse the entire multidimensional array:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int element = (*ptr)[j]; // Access each element in the current row.
// Perform operations with 'element'.
}
ptr++; // Compare it with another format of asking to move to the next row.
}
10
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ A linked list is a collection of nodes. Each node has two parts: data and a reference to the next
node. Unlike arrays, linked lists don't require contiguous memory allocation. They can easily grow
or shrink during runtime. Common types of linked lists include:
➢ Doubly linked lists (each node points to both the next and previous), and
➢ Circular linked lists (the last node points back to the first).
11
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ #include <iostream>
❑ int main() {
❑ // Create nodes. Here nullptr has three address because of the Node structure definition
❑ Node* head = nullptr; // Initialize an empty Address for first node we call it head
❑ Node* second = nullptr; // Initialize an empty Address for second node we call it second
❑ Node* third = nullptr; // Initialize an empty Address for third node we call it third
12
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
// Allocate memory for the first node. Nod structure has the data and the address of the next by means of the
pointer
❑ head = new Node(); // new modifies head from null
❑ second = new Node(); // Allocate memory for the second node.
❑ third = new Node(); // Allocate memory for the third node.
❑ // Assign data and link for the created nodes to manage the nodes. The arrow -> is an operator used in C++
to access members of a structure or class through a pointer
❑ head->data = 1; // assigns the value 1 to the ‘data’ member of the ‘head’ node.
❑ head->next = second;
❑ second->data = 2;
❑ second->next = third;
❑ third->data = 3;
❑ third->next = nullptr; // Mark the end of the list. 13
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
Data:1 Address:000002543E463250
Data:2 Address:000002543E463610
Data:3 Address:0000000000000000
14
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ In C++, pointers play a crucial role in representing and manipulating tree structures, such as:
1. Binary trees,
2. Binary search trees
3. Hierarchical data structures
❑ Trees are used to organize data hierarchically, making them suitable for tasks like:
1. Searching
2. Sorting
3. Conducting complex relationships
❑ In tree structures, a pointer points to a node, and each node can have multiple child nodes. The organization
of nodes and their connections forms the tree's structure. Pointers are used to traverse the tree, access data,
and manipulate nodes.
❑ A common type of tree structure is the Binary tree, where each node can have at most two children:
1. Left child
2. Right child
Pointers to these children are used to navigate the tree.
15
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
#include <iostream>
// Define a binary tree node structure by assigning the left and right nodes’ address
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
// This structure has two values: one for TreeNode (root) and the other for data- It also has to addresses one for
left one for right
TreeNode(int val) : data(val), left(nullptr), right(nullptr) {} // This is a constructor see the next slide
};
16
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
Constructor:
TreeNode(int val): This is the constructor declaration. It specifies a constructor for the TreeNode structure that
takes an integer argument val. This argument typically represents the data or value that you want to assign to the
data member of the TreeNode object being constructed.
: (Initialization List): This colon is used to introduce the initialization list, which is a way to initialize the member
variables of the TreeNode object that is being created.
17
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
Constructor:
data(val): This part of the initialization list assigns the value of val to the data member, initializing the node's data.
left(nullptr): This part initializes the left member of the TreeNode object with nullptr, indicating an initially empty
or unconnected left child.
right(nullptr): This part initializes the right member of the TreeNode object with nullptr, indicating that the right
child of the node is initially unconnected.
18
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
int main() {
// Create tree nodes and establish connections.
TreeNode* root = new TreeNode(10); // Create the root node and initialize it with a value of 10.
root->left = new TreeNode(5); // Create a left child node with a value of 5 and connect it to the root.
root->right = new TreeNode(15); // Create a right child node with a value of 15 and connect it to the root.
// Clean up memory
delete root->left;
delete root->right;
delete root;
return 0;} 19
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ Graphs are versatile data structures used to represent complex relationships between entities. In
C++, graphs are often implemented using pointers to represent nodes (vertices) and edges. Pointers
play a crucial role in linking nodes and navigating the graph.
❑ A graph is a collection of nodes (vertices) and edges (connections) that link these nodes. Each node
can be connected to one or more other nodes. In C++, you can represent a graph using structures or
classes for nodes, and pointers to establish connections between nodes.
❑ Pointers are used to navigate the graph, visit neighboring nodes, and perform various graph
algorithms:
1. Breadth-first search (BFS)
2. Depth-first search (DFS)
20
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
#include <iostream>
#include <vector>
// Define a graph node structure. We define a GraphNode structure to represent a node in the graph.
each node has data and a vector of pointers to its neighboring nodes.
struct GraphNode {
int data;
std::vector<GraphNode*> neighbors;
GraphNode(int val) : data(val) {} // This is a constructor please see the next slide
};
21
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ Constructors in C++:
22
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
23
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
int main() {
// Create graph nodes.
GraphNode* nodeA = new GraphNode(100);
GraphNode* nodeB = new GraphNode(200);
GraphNode* nodeC = new GraphNode(300);
❑ In these lines of code, you are creating three nodes (nodeA, nodeB, and nodeC) for a graph data
structure. Each node is assigned a unique integer value: nodeA has a value of 100, nodeB has a
value of 200, and nodeC has a value of 300.
❑ These nodes will serve as individual points or entities within the graph, and the assigned values can
represent various kinds of data or information associated with each node.
24
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Advanced data structures like linked lists, trees, and graphs with pointers.
❑ In C++, a function pointer is a variable that can store the memory address of a function. It provides
a way to call a function indirectly through the pointer, making it possible to choose and execute
different functions at runtime.
❑ Function pointers are commonly used for?:
1. Callbacks
2. Implementing custom function dispatch
3. Enabling dynamic behavior in programs
26
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Exploring function pointers and their applications.
#include <iostream>
// Define two functions with the same signature.
int add(int a, int b) {
return a + b;}
int subtract(int a, int b) {
return a - b;}
int main() {
// Declare a function pointer.
int (*operation)(int, int);
27
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Exploring function pointers and their applications.
❑ In software development, callback mechanisms are a powerful way to customize or extend the
behavior of a function without altering its core code. Function pointers play a crucial role in
implementing these mechanisms. Here are the general step to realize such useful mechanism:
29
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Using function pointers for callback mechanisms.
// Step 1: Define Callback Function Type (you can go without typedef also)
typedef double (*Callback)(double, int); // the pointer Callback creates address for a function with two types of data
30
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Using function pointers for callback mechanisms.
31
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Using function pointers for callback mechanisms.
int main() {
// Step 4: Assign Callback Function1 or 2 to the Pointer (call_back)
Call_back = Sine_F; // For sine series
// OR
// Call_back = Cos_F; // For cosine series
//It is also possible to declare like this: Callback call_back = Sine_F; but we already initialized in step3
❑ Dynamic function dispatch is a fundamental concept in OOP that allows you to call the appropriate
method or function based on the runtime type of an object.
❑ In C++, dynamic function dispatch is primarily achieved through pointers to base classes and virtual
functions. This mechanism enables polymorphism, which is a key feature of object-oriented programming.
For mplementing Dynamic Function Dispatch with Pointers in C++, we can go through:
• Polymorphism
• Base Class and Derived Classes
• Virtual Functions
• Pointers to Base Class
34
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Implementing dynamic function dispatch with pointers.
35
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Understanding double pointers and their uses.
❑ In C and C++, a double pointer is a pointer to a pointer. It's a variable that holds the memory
address of another pointer. Double pointers are often used when you need to work with:
36
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Understanding double pointers and their uses.
#include <iostream>
int main() {
int x = 10; // An integer variable
int *ptr1 = &x; // A pointer to x
int **ptr2 = &ptr1; // A double pointer to ptr1
// Display the original variable and its value OUTPUT:
std::cout << "Original Variable (x): " << x << std::endl; Original Variable (x): 10
// Modify the value using the pointer Modified Variable (x): 20
*ptr1 = 20; Final Modified Variable (x): 30
// Display the modified value
std::cout << "Modified Variable (x): " << x << std::endl;
// Modify the value using the double pointer
**ptr2 = 30;
// Display the final modified value
std::cout << "Final Modified Variable (x): " << x << std::endl;
return 0;} 37
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Understanding double pointers and their uses.
#include <iostream>
int main() {
int x = 10; // An integer variable Pointers and double pointers can be reassigned!
int y = 20; References can’t be reassigned!
int ref = x; Original Variable (x): 10
int* ptr1 = &x; // A pointer to x
ptr1: 10
int** ptr2 = &ptr1; // A double pointer to ptr1
std::cout << "Original Variable (x): " << x << std::endl; Modified Variable (x): 10
std::cout << "ptr1: " << *ptr1 << std::endl; Modified ptr1 directly: 20
ptr1 = &y; Modified ptr1 by ptr2: 30
std::cout << "Modified Variable (x): " << x << std::endl; Final Modified Variable (x): 10
std::cout << "Modified ptr1 directly: " << *ptr1 << std::endl; x = 10, y = 30, ref = 30
**ptr2 = 30;
std::cout << "Modified ptr1 by ptr2: " << *ptr1 << std::endl;
std::cout << "Final Modified Variable (x): " << x << std::endl;
ref = y;
std::cout << "x = " << x << ", y = " << y << ", ref = " << ref << std::endl;
return 0;} 38
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Function pointers to handle arrays of functions.
❑ In C and C++, you can use function pointers to create arrays of functions. This technique is
particularly useful when you want to call different functions dynamically based on certain
conditions or inputs. Function pointers provide flexibility and enable you to choose which function
to execute at runtime.
#include <iostream>
// Initiate function array pointer
// Define Array of functions based on number of function
// Define operations of the given function
// call function and variables by their index array
//output
39
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Function pointers to handle arrays of functions.
functionArray[0] = &Add;
functionArray[0] = &Subtract;
functionArray[0] = &Multiply;
//Define functions
int a = 10;
int b = 20;
Int result = functionArray[0](a,b); // Calls the Add function
40
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Real-world examples of complex pointer-to-function scenarios.
41
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Memory safety with pointers in languages like Rust.
❑ Rust and C++ are distinct languages with their own compilers and ecosystems. To use Rust, you
need to install the Rust programming language and its compiler separately, and it is not a header
or part of the C++ language. Rust offers a different approach to system-level programming,
focusing on memory safety and concurrency, while C++ provides a long-established approach
with its own set of features and libraries.
❑ Pointers in C++ do not provide the same level of safety as Rust due to differences in their
language design and memory management models. While C++ provides mechanisms to work
with pointers, it lacks the strong memory safety guarantees that Rust offers.
42
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Strategies for avoiding common pointer errors (e.g., null pointer, dangling pointer).
Dangling Pointer:
A dangling pointer is a pointer that continues to reference a memory location after the
memory it points to has been deallocated (freed) or goes out of scope. Accessing a
dangling pointer can lead to undefined behavior or crashes.
43
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Strategies for avoiding common pointer errors (e.g., null pointer, dangling pointer).
Common solutions for solving errors
44
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Smart pointers in C++ and their role in memory management.
Smart Pointers: They are C++ objects that act as wrappers around raw pointers, providing automatic
memory management. They help prevent memory leaks and manage the lifetime of dynamically
allocated objects. We have two smart pointers: Shared and Unique pointers.
1. Shared Pointers: It is a type of smart pointer in C++ that allows multiple shared pointers to
share ownership of the same dynamically allocated object. Memory is automatically
deallocated when the last shared pointer that owns it goes out of scope, preventing premature
deallocation.
std::shared_ptr<int> smart= std::make_shared<int>(2032);
2. Unique Pointers: It is a type of smart pointer in C++ that represents exclusive ownership of a
dynamically allocated object. Unlike shared pointers, only one unique pointer can own the
object, and when the unique pointer goes out of scope, the associated memory is automatically
deallocated.
std::unique_ptr<int> smart = std::make_unique<int>(2023);
45
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Memory safety with pointers in languages like Rust.
Memory Safety with Pointers in Rust:
Memory safety is a critical concern in systems programming languages like Rust. Rust is designed to provide
memory safety guarantees while still allowing low-level control over hardware resources. One of Rust's
strengths is its powerful and strict type system. The Rust compiler enforces memory safety guarantees at
compile time, catching many potential issues before the code is even run.
how Rust achieves memory safety with pointers:
1. Ownership System
2. Borrowing and References
3. No Null Pointers
4. Ownership Transfers
5. Lifetimes
6. Smart Pointers
7. Unsafe Blocks
8. Compiler-Enforced Guarantees
46
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Memory safety with pointers in languages like Rust.
Ownership System:
In C++, ownership of resources (typically memory) is primarily managed manually by the programmer. C++
does not have a built-in ownership system like Rust, but it relies on a set of conventions and programming
practices to manage ownership. Here's an overview of how ownership works in C++:
✓ Dynamic Memory Allocation: Memory is allocated manually using operators like new and new[] for
objects on the heap (dynamic memory location).
✓ Ownership Transfer: Ownership of resources can be transferred between objects using move
semantics.
✓ Ownership Release: The delete operator is used to deallocate memory and release ownership.
✓ Manual Resource Management: Resources like file handles are manually managed by acquiring and
releasing them explicitly.
47
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Memory safety with pointers in languages like Rust.
Ownership System:
✓ Ownership Conventions: C++ follows guidelines like the "Rule of Three" and "Rule of Five" to ensure
proper resource management.
✓ Smart Pointers (Optional): C++ provides smart pointers that can automatically manage memory,
reducing the risk of memory leaks.
✓ Resource Management Libraries: Developers can use libraries like Boost.Asio and Boost.Filesystem
to assist in managing specific types of resources.
48
CSI2372 - Advanced Programming Concepts with C++
Module 1: Foundations of C++ Programming
Session 3: Pointers, Memory Management, and Efficiency
Memory safety with pointers in languages like Rust.
Rule of Three:
The Rule of Three states that if a class manages a dynamically allocated resource (like memory), it should
define or delete the copy constructor, copy assignment operator, and destructor.
This ensures proper handling of resource ownership, preventing memory leaks and double deletions when
objects are copied or destroyed.
49
Thank You
50
Password
51
Password-CSI-Monday
52