0% found this document useful (0 votes)
7 views24 pages

4 Lecture DSOOP DMAandRecursion DrTahirNawaz

The document provides an overview of dynamic memory allocation and recursion in C++. It explains the concepts of stack and heap memory, the use of 'new' and 'delete' operators for memory management, and the principles of recursion including base conditions. Additionally, it discusses the advantages and disadvantages of recursion compared to iterative solutions.

Uploaded by

Sajid Ali
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)
7 views24 pages

4 Lecture DSOOP DMAandRecursion DrTahirNawaz

The document provides an overview of dynamic memory allocation and recursion in C++. It explains the concepts of stack and heap memory, the use of 'new' and 'delete' operators for memory management, and the principles of recursion including base conditions. Additionally, it discusses the advantages and disadvantages of recursion compared to iterative solutions.

Uploaded by

Sajid Ali
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/ 24

EC-204 Data Structures and Object

Oriented Programming

Dynamic Memory Allocation & Recursion

Dr Tahir Nawaz
Website: https://www.tahirnawaz.com
Email: [email protected]
Dynamic Memory Allocation
Introduction
• A good understanding of dynamic memory allocation in
C++ is essential to become a good programmer.
Memory for a C++ program is divided into two parts:

• The stack – All variables/arguments inside the


function(s) will take up memory from the stack, which
is fixed by OS and cant grow if needed during
runtime.

• The heap – This is unused memory of the program


and can be used to allocate the memory dynamically
when program runs and is often referred to as large
free store or pool of memory
Introduction
#include <iostream>
using namespace std; Stack Application
memory
int total;
int Square(int x){
return x*x;
}

int SquareOfSum(int x,int y){ square()


int z = Square(x+y); x
return z; SOS()
} x, y, z
Stack main()
int main(){
frame a, b
int a=4,b=8;
total = SquareOfSum(a,b);
cout<<"output = " <<total;
} total

Global

• We need to careful about stack overflow!


Introduction (contd.)
• Many a times, we may not know in advance how much
memory we will need to store particular information in a
defined variable and the size of required memory can
only be determined at run time.

• In such cases, we can allocate memory at run time


within the heap for the variable of a given type using a
special operator in C++.
Introduction (contd.)
• This special operator actually returns the address of the
space allocated and is called new operator.

• Likewise If we are not in need of dynamically allocated


memory anymore, we can use another special operator
that is called delete operator

• delete operator de-allocates memory that was previously


allocated by new operator.
Using the new operator
• There is following generic syntax to use new operator to
allocate memory dynamically for any data-type.
new data-type;

• Here, data-type could be any built-in data type


including an array or any user defined data types include
class or structure.

• For example we can define a pointer to type double and


then request that the memory be allocated at execution
time using new operator as follows:

double* pvalue=NULL; //Pointer initialized with null


pvalue = new double; //Request memory for variable
Using the new operator (contd.)
• It may be possible that the memory may not have been
allocated successfully due to unavailability of any free
space. So it is good practice to check if new operator is
returning NULL pointer and take appropriate action as
below:
double* pvalue = NULL;
if( !(pvalue = new double )) {
cout << "Error: out of memory." <<endl;
exit(1);
}

• The malloc() function (from C) still exists in C++, but the


use of new operator is generally recommended and
preferable in C++
Using the delete operator
• At any point, when you feel a variable that has been
dynamically allocated is not anymore required, you can
free up the memory that it occupies using the delete
operator

• The syntax for using the delete operator is as follows:

delete pvalue;

• The above statement releases memory pointed to by the


pvalue pointer
Example
#include <iostream>
using namespace std;

int main () {
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable

*pvalue = 2949.41; // Store value at allocated address


cout << "Value of pvalue : " << *pvalue << endl;

delete pvalue; // free up the memory.

return 0;
}
Dynamic memory allocation for Arrays
• Suppose we want to allocate memory for an array of
characters, i.e., string of 20 characters. Using the same
syntax what we have used above we can allocate
memory dynamically as shown below.

char* pvalue = NULL;// Pointer initialized with


null
pvalue = new char[20];// Request memory for the
variable

• In order to free up the dynamically allocated memory for


an array, we use the following statement

delete [] pvalue; // Delete array pointed to by


pvalue
Dynamic memory allocation for Objects
• Objects are no different from simple data types. For
example, consider the following code where we are going
to use an array of objects to clarify the concept

#include <iostream>
using namespace std;

class Box {
public:
Box() {cout << "Constructor called!" <<endl;}
~Box() {cout << "Destructor called!" <<endl;}
};
int main() {
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // Delete array
return 0; }
Dynamic memory allocation for Objects
• In the example we have allocated memory for an array of
four Box objects. So the constructor would be called four
times and similarly while deleting these objects, destructor
will also be called same number of times.

• If we compile and run the code, this would produce the


following result
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!
Recursion
Introduction
• Recursion refers to the process in which a function is
repeatedly called by itself in order to solve a more
complex problem

• Such a function that repeatedly calls itself is called the


recursive function and the process is called recursion.

• Basically, recursion process involves dividing the


problem into sub-tasks within a function and calling it
repeatedly to achieve the final solution

• Generally, a problem that is being solved using recursion


could be solved using iteration (looping) too; however,
the latter approach often requires more effort and time to
solve the same problem
How does it work?
• Recursion process continues until the final solution to the
problem under consideration is reached.

• Each time the part of the solution is found, it is stored in


the form of stack data structure in the memory and at
last, popped out to get the final solution.

• As we approach the final solution, there is a ‘base


condition’ that should be checked to get out of the
recursion process, thus avoiding the recursion process
to get into the infinite loop. If, for any reason, the base
case fails to work, the program will fall into an infinite
loop and we will never reach the solution of the program.
How does it work? (contd.)
• In C++, recursion works as follows:

recurse()
{ Recursive
... .. ... Call
recurse();
... .. ...
}

int main()
{
... .. ...
recurse();
Function
... .. ...
Call
}
How does it work? (contd.)
• Will the following program continue forever?

#include <iostream>
using namespace std;

void recurse (int count) //Each call gets its own


count
{
cout<< count <<"\n";
recurse ( count + 1 );
}

int main()
{
recurse ( 1 ); //First function call
}
How does it work? (contd.)
• In the previous program, computer keeps function calls
on a stack and once too many are called without ending,
the program will crash.
• This simple program shows the number of times the
recurse function has been called by initializing each
individual function call's count variable one greater than
it was previous by passing in count + 1.
• Actually, it is not a function restarting itself, it is hundreds
of functions that are each unfinished with the last one
calling a new recurse function.
• So recursion normally needs a condition where the
function will not call itself (and therefore finally exit!) and
is termed the ‘base case’ of the function.
How does it work? (contd.)
• Following function has got a base condition! Tell me the
output of this program!
#include <iostream>
using namespace std;

void printnum ( int begin )


{
cout<< begin;
if ( begin < 3 )
{
printnum ( begin + 1 );
}
cout<< begin;}

int main()
{
printnum(1);
}
How does it work? (contd.)
• Lets work out the output!
Function Call Recursive Call 1 Recursive Call 2

• Output?
123321
Tail vs. Head Recursion
• Tail Recursion: Some work is performed and then the
recursive call is made

• Head Recursion: Recursive call is made before the real


work is performed in the function body

Tail Recursion Head Recursion


Advantages and Disadvantages
• Advantages
– Shorter and cleaner code due to less number of code lines
– Recursion helps solving complex and larger problems effectively

• Disadvantages
– More stack space consumed than an equivalent iterative
program
– Higher processing time
– Error debugging is more difficult as compared to the iterative
program.
Acknowledgements/References
• https://www.tutorialspoint.com/cplusplus/index.htm

• https://www.cplusplus.com/

• https://www.cprogramming.com/

• https://www.youtube.com/watch?v=_8-ht2AKyH4

• Deital and Deital, “C++ How to Program”, Latest Edition

• Stroustrup, “Programming – Principles and Practice


Using C++”, Latest Edition

You might also like