Pointers and Dynamic Memory Allocation
Pointers and Dynamic Memory Allocation
Pointers and Dynamic Memory Allocation
MEMORY ALLOCATION
Presented by
Er.
Assistant Professor
Applied Science(CSE)
Chandigarh University
Gharuan (Mohali).
1
1.Need of Pointers
1. "Suppose you know your friend name ‘Rengan’. He is
living in Chennai. U have these two details only but you
want to meet him urgently.
2. How will u find your friend’s home without his address
(which place, street & door number)?
It is very difficult to find his home. Then you are going
to everyone’s home and asking whether my friend is there
or not?.
How long time will it take to find him?
But with his address you can find him within a few
minutes.
2
This same thing is applicable in our programs.
In our program we may use a lot of variable. If you
are going to a use particular variable then CPU will
search all the variables from top to bottom. It will
take some amount of time.
Suppose if you know the address, it is very easy to
catch it.
Pointer is a variable (like int, float, char,...) which
holds address of another variables.
Pointer is the most important concept in case of
System programming or CORE programming coz it
allows direct access to memory locations
3
1. e.g.:-
2. int a=10;
3. int *pa=&a;
4. cout<<<*pa;
At the Compile time, The compiler Checks the Syntax
At the Run time, it execute the first line then it
allocate 2 bytes memory of var a with Some address.
In the next line we are getting the address into *pa
and finally we r displaying the what is the value in
the address.
Pointers are generally useful in the context where we
need a continuous memory allocation. Using pointers
dynamic allocation of memory is achieved 4
2.What is Pointer?
• A variable that holds a memory address.
• This address is the location of another object
in the memory.
• Pointer as an address indicates where to find
an object.
Not all pointers actually contain an address
example NULL pointer.
Value of NULL pointer is 0.
5
• Pointer can have three kinds of content in it
1) The address of an object, which can be
dereferenced.
2) A NULL pointer.
3) Invalid content, which does not point to an
object.
(If p does not hold a valid value, it can crash the
program)
• If p is a pointer to integer, then
– Int *p
6
It is possible in some environments to have
multiple pointer values with different
representations that point to same location in
memory.
7
3.Declaring pointer
Data-type *name;
* is a unary operator, also called as
indirection operator.
Data-type is the type of object which the
pointer is pointing.
Any type of pointer can point to anywhere
in the memory.
* is used to declare a pointer and also to
dereference a pointer.
8
When you write int *,
compiler assumes that any address that it
holds points to an integer type.
m= &count;
it means memory address of count variable is
stored into m.
& is unary operator that returns the memory
address.
i.e. & (orally called as ampersand) is returning
the address.
so it means m receives the address of count.
9
Suppose, count uses memory
Address 2000 to store its value 100.
so, m=&count means m has 2000
address.
2000 count=100
q= *m
it returns the value at address m.
value at address 2000 is 100.
so, q will return value 100.
i.e. q receives the value at address m.
4.Address-of operator(&)
• It is used to reference the memory address of
a variable.
• When we declare a variable, 3 things happen
– Computer memory is set aside for variable
– Variable name is linked to that location in memory
– Value of variable is placed into the memory that
was set aside.
Int *ptr;
declaring variable ptr which holds the value
at address of int type
int val =1;
assigning int the literal value of 1
ptr=&val;
dereference and get value at address stored in
ptr
int deref =*ptr
cout<< deref;
Output will be 1
5.References and Pointers
There are 3 ways in C++ to pass arguments to a
function
1. call-by-value
2. call-by-reference with reference argument
3. call-by-reference with pointer argument
The differences between the last two are:
The address named as a reference can not be
altered. But because pointer is a variable, the
address in the pointer can be changed.
13
5.(Cont..)
• References do not require the indirection operator
to locate the final value being accessed, whereas
pointers do. References are automatically or
implicitly dereferenced, whereas pointers must be
explicitly dereferenced.
14
Example
// Find a cube of a variable with a pointer argument
1. #include <iostream>
2. using namespace std;
3. void cube (int *); // prototype
4. int main ( )
5. {
6. int number = 5;
7. cout << ”The original value of number is” <<
number << endl;
8. cube (&number);
15
Example (Cont..)
9. cout << ”\n The new value of number is “<< number
<<endl;
10. return 0;
11. }
12. void cube ( int *nptr)
13. {
14. *nptr =(*nptr)*(*nptr)*(*nptr);
15. }
17
6.(Cont..)
• Assume that array int arr [5] has been declared
and its first element is at location 100 in memory.
• Assume pointer int *ptrarr has been initialized to
the beginning address of arr, i.e.; 100.
18
6.(Cont..)
For example, the statement
ptrarr +=2=100+2*2=104
ptrarr -=1 =104-2*1=102
++ptrarr = 104
• Finally, pointer variables may be subtracted from
another. For example, if ptrarr 2 = 100 and ptrarr1
= 102 then
x = ptrarr2 –ptrarr1=2
19
6.(Cont..)
Pointer arithmetic is meaningless unless performed on
an array.
// using strcpy and strncpy
1. #include <iostream>
2. #include <string>
3. using namespace std;
4. int main ( )
5. { char x [ ] = “Happy Birthday to you”;
6. char y [ 25 ], z [15 ];
7. cout << ”The string in array x is:”<< x<< ”\n The string in
array y is: “ << strcpy(y, x)<< ”\n”;
8. strncpy (z, x, 14); // does not copy null character
9. z [14] = ‘\0’;
10. cout << ”The string in array z is: “ << z << endl;
11. return 0;
20
12. }
Example (Cont..)
21
(Cont..)
Functions strcpy( ) copies its second argument (a string)
into its first argument which must be large enough to store
the string and the terminating null character.
strncpy( ) is equivalent to strcpy( ) except that strncpy( )
specifies the number of characters to be copied from the
string into the array.
Note that the function strncpy( ) does not necessarily copy
the terminating null character of its second argument – a
terminating null character is written only if the number of
characters to be copied is at least one more than the length
of the string.
22
Example
// using strcat and strncat
1. #include <iostream>
2. #include <string>
3. using namespace std;
4. int main ( )
5. {
6. char s1[20 ]=”Happy ”;
7. char s2 [ ] = “New Year”;
8. char s3 [40] = “ “;
9. cout << ”s1= “ << s1 << ”\n s2 = “ << s2;
10. cout << ”\n strcat ( s1, s2) = “ << strcat (s1, s2);
11. cout << ”\n strncat (s3, s1, 6) = “<< strncat (s3, s1, 6);
12. cout << ”\n strcat (s3, s1,) = ” << strcat(s3, s1) << endl;
13. return 0;
23
14. }
Example (Cont..)
The output of the above program is:
s1 = Happy
s2 = New Year
strcat (s1, s2) = Happy New Year
strncat (s3, s1, 6) = Happy
strcat (s3, s1) = Happy Happy New Year
24
(Cont..)
Function strncat ( ) appends a specified number of
characters from the second string to the first string.
A terminating null character is appended to the
result.
Assuming that strcmp ( ) and strncmp ( ) return 1
when their argument are equal is a logic error.
Both functions return 0 ( C++’s false value ) for
equality.
Therefore, when testing two strings for equality,
the result of the strcmp ( ) or strncmp ( ) function
should be compared with 0 to determine if the
strings are equal.
25
Example
// using strcmp and strncmp
1. #include <iostream>
2. #include <string>
3. using namespace std;
4. int main ( )
5. {
6. char *s1 = “Happy New Year”;
7. char *s2 = “Happy New Year”;
8. char *s3 = “Happy Holidays”;
9. cout << ”strcmp(s1, s2) = “ << strcmp (s1, s2)
10. << "\n strcmp (s1, s3) = " << strcmp (s1, s3)
11. << ”\n strcmp (s3, s1) = “ << strcmp (s3, s1);
26
Example (Cont..)
12. cout << ”\n\n strncmp (s1, s3, 6) = “ << strncmp (s1, s3, 6)
13. << ”\n strncmp (s1, s3, 7 ) = “ << strncmp (s1,s3, 7)
14. << ”\n strncmp (s3, s1, 7) = “ << strncmp (s3, s1, 7)
15. <<endl;
16. return 0;
17. }
27
Example (Cont..)
The output of the above program is:
strcmp (s1, s2) = 0
strcmp (s1, s3) = 1
strcmp (s3, s1) = -1
28
7.Array Name as Pointers
• An array name is a pointer constant.
• The value of the pointer constant is the
address of the first element.
• Thus, if val is the name of an array, val and
&val [ 0 ] can be used interchangeably.
Creating an array also creates a pointer
int grade [ 2 ]
grade [ 0 ] grade [ 1 ]
*grade *(grade + 1)
29
Example
// Pointer to arrays
1. #include <iostream>
2. using namespace std;
3. void printarray ( int*, int)
4. int main ( )
5. {
6. const int arraysize = 5;
7. int grade [arraysize] = { 93, 88, 94, 91, 82};
8. int *ptr;
9. ptr = grade; // or ptr=&grade [ 0 ];
10. printarray (grade, arraysize);
30
Example (Cont..)
11. for ( int i = 0; i < 5; i++)
12. cout << ”\n Element “<< i <<” is “ << *ptr++;
13. // or *(grade+i)
14. cout << endl;
15. return 0;
16. }
17. void printarray ( int *ptrgrade, int MAX)
18. {
19. int constant = 10;
20. for (int i = 0; i < MAX; i++)
21. *ptrgrade++ += constant;
22. } 31
Example (Cont..)
The output of the above program is:
Element 0 is 103
Element 1 is 98
Element 2 is 104
Element 3 is 101
Element 4 is 92
32
Example
// Example of pointers and strings and const data
1. #include <iostream>
2. using namespace std;
3. void printc (const char * );
4. int main ( )
5. {
6. char string [ ] = “print characters of a string”;
7. cout << ”The string is: \n”;
8. printc (string);
9. cout << endl;
10. return 0;
11. } 33
Example (Cont..)
11. void printc (const char *sptr) // sptr is “read-only” pointer
12. {
13. for ( ; *sptr !=’\0’; sptr ++) // no initialization
14. cout << *sptr;
15. }
34
Example
// converting lowercase letter to uppercase letters
// using non-constant pointer
1. #include <iostream>
2. #include <ctype>
3. using namespace std;
4. void convert ( char *);
5. int main ( )
6. {
7. char string [ ] = “characters and $32.98”;
8. cout << “The string before conversion is: ” << string;
9. convert (string);
35
Example (Cont..)
10. cout << ”\n The string after conversion is: “ << string <<
endl;
11. return 0;
12. }
13. void convert ( char *sptr)
14. {
15. while (*sptr !=’\0’)
16. {
17. if ( *sptr >= ’a’ && *sptr <= ’z’)
18. *sptr = toupper ( *sptr); // convert to uppercase
19. ++sptr;// move sptr address to the next character
20. }
21. } 36
Example (Cont..)
The output of the above program is:
The string before conversion is: characters and $ 32.98
The string after conversion is: CHARACTERS AND $
32.98
37
8.Pointer Arrays
The declaration of an array of character pointer is
an extremely useful extension to single string
declaration.
For example, the declarations
char *seasons [ 4 ];
create an array of four elements, where each
element is a pointer to a character.
38
(Cont..)
• As individual pointers, each pointer can be
assigned to point to a string using string
assignment statements.
• Thus, the statements
seasons [ 0 ] = “Winter”;
seasons [ 1 ] = “Spring”;
seasons [ 2 ] = “Summer”;
seasons [ 3 ] = “Fall”; // sting lengths may differ
39
9.Initializing arrays of pointers to
strings
The initialization of the seasons array can also
be incorporated directly within the definition
of the array as follows:
char *seasons [ 4 ] = {“Winter”, “Spring”,
“Summer”, “Fall”};
40
Example
// string and pointer example
1. #include < iostream>
2. using namespace std;
3. int main ( )
4. {
5. int n;
6. char *seasons [ ] = { “Winter”, “Spring”, “Summer”, “Fall”};
7. cout << ”\n Enter a month (use 1 for Jan, 2 for Feb, etc):”;
8. cin >> n;
9. n = (n % 12) / 3; // create the correct subscript
10. cout << “The month entered is a << seasons [ n ]// or * (seasons + n)
<< ”month” << endl;
11. return 0;
12. }
41
Example (Cont..)
The output of the above program is:
Enter a month ( use 1 for Jan 2 for Feb, etc.) :
12
The month entered is a Winter month
42
Example
The following example is the modification to
previous example in this case a function is used to
print seasons.
1. #include <iostream>
2. using namespace std;
3. void st_pt ( char *ys [ ], int n);
4. int main ( ){
5. int n;
6. char *seasons [ ] = { “Winter”, “Spring”, “Summer”,
“Fall”};
7. cout << “\n Enter a month ( use 1 for Jan, etc.):”;
8. cin >> n;
43
Example (Cont..)
9. st_pt (seasons, n);
10. return 0;
11. }
12. void st_pt (char *ys [ ], int n)
13. {
14. n = (n%12)/3;
15. cout << ”The month entered is a “ << *(ys + n)
16. <<” month.” <<endl;
17. }
44
Pointers are exceptionally useful in constructing
string-handling functions when pointer notation is
used in place of subscripts to access individual
characters in a string, the resulting statements are
both more compact and more efficient.
45
10. Benefits of pointer
• Pointers are used in situations when passing actual values is
difficult or not desired.
• To return more than one value from a function.
• They increase the execution speed.
• The pointer are more efficient in handling the data types .
• Pointers reduce the length and complexity of a program.
46
• The use of a pointer array to character string results in
saving of data.
• To allocate memory and access it( Dynamic memory
Allocation).
• Implementing linked lists, trees graphs and many other data
structure.
47
Uses of pointer to function
• Pointers are certainly awkward and off-putting and thus
this feature of pointer is used for invoking a function
• There are several possible uses :
(a) In writing memory resident program.
(b) In writing viruses, or vaccines to
remove the viruses.
(c) In developing COM/DCOM component
(d) In VC++ programming to connect events to
function calls.
48
11. Pointers to objects
Pointers can point to objects as well as to
simple data types and arrays. We’ve seen
many examples of objects defined and given a
name, in statements like
Distance dist;
where an object called ‘dist’ is defined to be
of the Distance class
49
Continue..
• Sometimes, however, we don’t know, at the
time that we write the program, how many
objects we want to create.
• When this is the case we can use new to
create objects while the program is running.
• As we’ve seen, new returns a pointer to an
unnamed object.
50
// accessing member functions by pointer
1. #include <iostream>
2. using namespace std;
3. class Distance //English Distance class
4. {
5. private:
6. int feet;
7. float inches;
8. public:
9. void getdist() //get length from user
10. {
11. cout << “\nEnter feet: “; cin >> feet;
12. cout << “Enter inches: “; cin >> inches;
13. }
51
14. void showdist() //display distance
15. { cout << feet << “\’-” << inches << ‘\”’; }
16. }
17. int main()
18. {
19. Distance dist; //define a named Distance object
20. dist.getdist(); //access object members
21. dist.showdist(); // with dot operator
22. Distance* distptr; //pointer to Distance
23. distptr = new Distance; //points to new Distance object
24. distptr->getdist(); //access object members
25. distptr->showdist(); // with -> operator
26. cout << endl;
27. return 0;
28. } 52
The main() function defines dist, uses the Distance
member function getdist() to get a distance from the
user, and then uses showdist() to display it.
53
12. this pointer
this->member-identifier
54
Continue..
• An object's this pointer is not part of the object
itself;
• it is not reflected in the result of a sizeof statement
on the object.
• Instead, when a non-static member function is called
for an object, the address of the object is passed by
the compiler as a hidden argument to the function.
• For example, the following function call:
myDate.setMonth( 3 ); can be interpreted this
way: setMonth( &myDate, 3 );
55
Continue..
• The object's address is available from within the
member function as the this pointer.
• Most uses of this are implicit.
• It is legal, though unnecessary, to explicitly use this
when referring to members of the class. For example:
1. void Date::setMonth( int mn )
2. {
3. month = mn; // These three statements
4. this->month = mn; // are equivalent
5. (*this).month = mn;
6. } 56
13. Pointers to Derived Classes
• C++ allows base class pointers to point to
derived class objects.
• Let we have –
– class base { … };
– class derived : public base { … };
• Then we can write –
– base *p1; derived d_obj; p1 = &d_obj;
– base *p2 = new derived;
57
Pointers to Derived Classes (contd.)
• Using a base class pointer (pointing to a derived
class object) we can access only those members
of the derived object that were inherited from
the base.
– It is different from the behavior that Java shows.
– We can get Java-like behavior using virtual functions.
• This is because the base pointer has knowledge
only of the base class.
• It knows nothing about the members added by
the derived class.
58
Pointers to Derived Classes (contd.)
• class base { • void main() {
• public: • base b1;
• void show() { • b1.show(); // base
• cout << “base\n”; • derived d1;
• } • d1.show(); // derived
• }; • base *pb = &b1;
• class derived : public base { • pb->show(); // base
• public: • pb = &d1;
• void show() {
• cout << “derived\n”; • pb->show(); // base
• } • }
• }; • All the function calls here are
statically bound
59
Pointers to Derived Classes (contd.)
• While it is permissible for a base class
pointer to point to a derived object, the
reverse is not true.
– base b1;
– derived *pd = &b1; // compiler error
• We can perform a downcast with the
help of type-casting, but should use it
with caution (see next slide).
60
Pointers to Derived Classes (contd.)
• Let we have –
– class base { … };
– class derived : public base { … };
– class xyz { … }; // having no relation with “base” or
“derived”
• Then if we write –
– base b_obj; base *pb; derived d_obj; pb = &d_obj; // ok
– derived *pd = pb; // compiler error
– derived *pd = (derived *)pb; // ok, valid downcasting
– xyz obj; // ok
– pd = (derived *)&obj; // invalid casting, no compiler error,
but may cause run-time error
– pd = (derived *)&b_obj; // invalid casting, no compiler
error, but may cause run-time error
61
Pointers to Derived Classes (contd.)
• In fact using type-casting, we can use pointer of any
class to point to an object of any other class.
– The compiler will not complain.
– During run-time, the address assignment will also succeed.
– But if we use the pointer to access any member, then it
may cause run-time error.
• Java prevents such problems by throwing
“ClassCastException” in case of invalid casting.
62
Pointers to Derived Classes (contd.)
• Pointer arithmetic is relative to the data type the
pointer is declared as pointing to.
• If we point a base pointer to a derived object and
then increment the pointer, it will not be pointing to
the next derived object.
• It will be pointing to (what it thinks is) the next base
object !!!
63
14. Static Binding
• Static binding occurs when an object is associated with a
member function based on the static type of the object.
• The static type of an object is the type of its class or the type
of its pointer or reference.
• A member function statically bound to an object can be
either a member of its class or an inherited member of a
direct or indirect base class.
• Since static binding occurs at compile time, it is also called
compile time binding.
64
Static Binding
• As we saw in the previous lecture, a publicly derived class
represents an "is a" relationship.
• This means that whenever we need a direct or indirect base
class object, we can use a derived class object in its place
because a derived class object savings object
account::statement()
is a base class object. name[]
balance
savings::statement()
account interest
student object
checking savings
account::statement()
name[]
balance
student checking::statement()
charges
student::statement()
school[] 65
Static Binding
• Using this account class hierarchy, whenever we need an
account object we can use a checking, student, or savings
object in its place.
• This is because every checking, student, and savings object
contains an account object.
• This is the essential characteristic of a hierarchy.
• Notice that it does not work the other way around.
• We cannot use an account object when we need a checking,
student, or savings object because an account object does
not have the necessary data members or member functions.
• If we attempt to do that a compile error will result.
66
Static Binding
student smith("Joe Smith", 5000, "UT");
student s(smith); s.statement();
checking c; c = s; c.statement();
account a; a = s; a.statement();
account a;
a = s; student s;
account::statement() account::statement()
name[] name[]
balance balance
checking::statement()
charges
student::statement()
school[]
68
Static Binding
• Static binding guarantees that we will never associate a
member function of a derived class with an object of a direct
or indirect base class.
• If that were to happen, the member function would attempt
to access data members that do not exist in the object. That
is because a base class object does not have an "is a"
relationship with a derived class object.
• Of course, we can go the other way around. That is, we can
associate a member function of a direct or indirect base
class with an object of a derived class as long as that
member function is accessible (i.e., public).
• That is what inheritance is all about and it works because we
have an "is a" relationship. 69
15. Upcasting
• We can assign pointers to derived class objects to point to
base class objects. We can also use derived class objects to
initialize references to base class objects.
• Using this account class hierarchy, whenever we need a
pointer to an account object, we can use a pointer to a
checking, student, or savings object. This is called upcasting
even though no cast operation is necessary.
• This is because every checking, student, and savings object
contains an account object. When we are pointing to a
checking, student, or savings object, we are also pointing to
an account object.
• When we are pointing to an account object, we do not have
access to a checking, student, or savings objects. 70
Upcasting
void print_account(account* p) { //pointer
p->statement();
}
int main() {
student smith("Joe Smith", 5000, "UT");
student* ps = &smith; ps->statement();
73
17. Dynamic Binding
• Dynamic binding occurs when a pointer or reference is
associated with a member function based on the dynamic
type of the object.
• The dynamic type of an object is the type of the object
actually pointed or referred to rather than the static type of
its pointer or reference.
• The member function that is dynamically bound must
override a virtual function declared in a direct or indirect
base class.
• Since dynamic binding occurs at run time, it is also called run
time binding.
74
Enabling Dynamic Binding
• Whenever we want a function to be dynamically bound, we
should define that function as virtual in a direct or indirect
base class.
• By doing so, we are turning on the dynamic binding
mechanism and allowing member functions to be selected at
run time based on the type of object pointed or referred to.
• Virtual functions should be used when we want to provide
member functions in our base class that define an interface
for application programs to use.
• The actual implementation of the virtual functions is either
provided by the base class or is overridden and implemented
as appropriate in derived classes.
75
Rules of Dynamic Binding
• Virtual functions cannot be static member functions.
• Second, the signature and return type must be the same for
all implementations of the virtual function.
• Third, while the function must be defined as a virtual
function within a direct or indirect base class, it need not be
defined in those derived classes where the inherited
behavior does not need to differ.
• And finally, the keyword virtual is only required within the
base class itself; derived class implementations of the
overridden function do not need to repeat the use of that
keyword.
• Once a member function is declared to be virtual, it remains
virtual for all derived classes. 76
18. But...back to static binding if...
• If the signature of the overridden function is not the
same as the declaration of the virtual function,
overriding does not occur and the virtual function is
simply hidden.
• In such cases, the virtual function invoked will be an
inherited function from a direct or indirect base
class determined at compile time.
• Or, if the function is invoked through an object
rather than a pointer or a reference, static binding
will take place instead!
77
19. Now, using Dynamic Binding
//account.h (Ex1705)
class account {
public:
account(const char* ="none", float=0);
virtual void statement(); //virtual function
private:
char name[32];
float balance;
};
//from main:
student smith("Joe Smith", 5000, "UT");
student* ps = &smith; ps->statement();
account a; account::vtbl
vptr account::statement()
name[] . . .
balance
student s; student::vtbl
First, the pointer to the object
must be dereferenced. vptr student::statement()
84
charges
Dynamic Binding Mechanism
• This cost is not as bad as it first seems. Many compilers do this
more efficiently.
• Second, to “simulate” dynamic binding, the application would
be implemented significantly differently.
• Each derived class would have to define a value to represent its
type so that the application could query the object at run time
to determine what type it was pointing to.
• Then, the application would have to downcast the pointer from
an account object to the correct type in order to access the
correct derived class member function.
• This would have to be done each time a derived class member
function needed to be accessed.
85
21. Disabling Dynamic Binding
• Once dynamic binding is enabled, an overridden member
function is bound to a pointer or reference based on the type of
the object pointed to.
• Dynamic binding is not in effect if an object is used instead of a
pointer or reference to an object.
• Dynamic binding is also not in effect if the member function is
qualified with a class name and the scope resolution operator.
• In this case, the function bound to the pointer is the member
function defined by the qualifying class.
(pa->account::statement(); )
• For example, if we assign the student object to an account object
and then invoke statement, static binding is in effect and the
account function is called:
account a = smith; 86
Making sure pointers are used
• We can force application programs to always use pointers to
base class objects instead of using pointers to derived class
objects or using objects directly by making the overridden
member functions protected or private in the derived
classes.
• This is a way to force applications to adhere to the defined
interface provided by the base class and to help ensure that
dynamic binding will be used.
• It causes compilation errors to result if the application
attempts to use static binding:
student* ps = &smith;
ps->statement(); //illegal access-protected member
smith.statement(); //illegal access-protected member
87
Use of Protected...
1. class account {
2. public:
3. account(const char* ="none", float=0);
4. virtual void statement();
5. private:
6. ...
7. };
8. class checking : public account {
9. ...
10. protected:
11. void statement();
12. };
13. class student : public checking {
14. ...
15. protected:
16. void statement();
17. };
18. app: student smith("Kyle smith", 5000, "UT");
19. account* pa = &smith;
20. pa->statement(); //okay 88
22. Memory Allocation
There are essentially two types of memory allocation
1. Static – Done by the compiler automatically
(implicitly).
90
Explicitly allocating memory in C++:
The ‘new’ Operator
• Used to dynamically allocate memory
• Can be used to allocate a single variable/object or an
array of variables/objects
• The new operator returns pointer to the type
allocated
• Examples:
– char *my_char_ptr = new char;
– int *my_int_array =new int[20];
– Mixed *m1 = new Mixed(1,1,2);
– Before the assignment, the pointer may or may not point to a legitimate
memory
– After the assignment, the pointer points to a legitimate memory. 91
Explicitly freeing memory in C++:
the ‘delete’ Operator
Used to free memory allocated with new operator
The delete operator should be called on a pointer to
dynamically allocated memory when it is no longer needed
Can delete a single variable/object or an array
delete PointerName;
delete [] ArrayName;
After delete is called on a memory region, that region
should no longer be accessed by the program
Convention is to set pointer to deleted memory to NULL
Any new must have a corresponding delete --- if not, the
program has memory leak.
New and delete may not be in the same routine.
92
The Heap
• Large area of memory controlled by the runtime
system that is used to grant dynamic memory
requests.
• It is possible to allocate memory and “lose” the
pointer to that region without freeing it. This is
called a memory leak.
• A memory leak can cause the heap to become full
• If an attempt is made to allocate memory from the
heap and there is not enough, an exception is
generated (error)
93
Why use dynamic memory allocation?
94
The . and -> operators
• The dot operator is used to access an object’s
members
– M1.Simplify();
– M1.num = 5;
• But how do we access an objects members if we only
have a pointer to the object?
• If we have M1_ptr = &M1, Perhaps we would use
(*(M1_ptr)).Simplify()
• A shorthand for this is the arrow operator
• M1_ptr->Simplifly() is equivelant
to(*(M1_ptr)).Simplify()
95
Thank you
96