Title: Storage Structures for Container Classes
1Chapter 2
- Storage Structures for Container Classes
2Outline
- Dynamic Variables and Pointers
- Container Classes
- linked structures
- class Linked
- Iterator
- Standard Template Library
- Function Templates
- Class Templates
3A Dynamic Variable
- is created and destroyed (dynamically) during
execution, which can save a lot of space in
memory. - is stored on the Heap, a large area of memory
- is never accessed directly.
- is accessed through pointer variables.
- Memory management
- Stack vs. Heap
- int b // b is created on stack, also called
static allocation, i.e., before the execution of
the program - variable (like b) created on stack is destroyed
when the function in which it was declared
returns, e.g. return 0 for variables declared in
main()
4A Pointer Variable
- Contains the address of a variable (usually, a
dynamic variable). - A pointer type is a type followed by an asterisk
- int iPtr // preferred way
- !!! NOTE This is equivalent to
- int iPtr
- or
- int iPtr
- Here, iPtr is a pointer variable (stored on the
stack), specifically, a pointer to an
int type variable.
stack
iPtr
pointer variable
5To Create A Dynamic Variable
- The new operator is used
- iPtr new int
- The execution of this statement creates a
dynamic variable (on heap) pointed to by pointer
variable iPtr (on stack) which holds the address
(e.g., 00101011) of the dynamic variable.
stack
heap
iPtr
?
00101011
00101011
pointer variable
dynamic variable
6To Access The Dynamic Variable
- We dereference the pointer variable.
- The dereference operator, , is placed in front
of the pointer variable iPtr - The dynamic variable can now be treated as an
ordinary int variable (on the heap). - For example,iPtr 5 // note to left
of iPtr
stack
heap
iPtr
5
pointer variable
dynamic variable
7To Destroy A Dynamic Variable
- The delete operator is used delete iPtr
- This deallocates the space for the dynamic
variable pointed to by pointer variable iPtr. - That space (on heap) can now be allocated for
another dynamic variable. - !!! NOTE the pointer variable iPtr still exists
(on stack), which will be deleted (automatically)
when the function in which it was declared
returns
stack
iPtr
GO OVER NOTES ON POINTERS
pointer variable
8Example 1 int type pointer
int p, q // asterisk needed for each
pointer variable p new int q new int p
55 q 0 cout ltlt p ltlt ltlt q ltlt endl q
p cout ltlt p ltlt ltlt q ltlt endl delete
p // delete the dynamic variable pointed to by
p delete q // delete the dynamic variable
pointed to by q // p and q are still alive
55 0
55 55
9Example 2 string type pointer
string sPtr sPtr new string cin gtgt
sPtr while (sPtr ! "") if
((sPtr).length() lt 6) cout ltlt sPtr ltlt " is
a small word." ltlt endl else cout ltlt sPtr
ltlt " is not a small word." ltlt endl cin gtgt
sPtr // while delete sPtr
10Example 2 string type pointer
- In the expression (sPtr).length() lt
6parentheses around sPtr are needed The
member-selection operator (the dot) has higher
precedence - Alternative notation the
dereference-and-select operator is -gt - sPtr-gtlength() lt 6
- This is equivalent to
- (sPtr).length() lt 6
11Example 3 class type pointer
int main() // regular object created on
stack Employee emp1 emp1.setName(Tom)
// create pointer variables (on stack)
Employee emp2, emp3 // use default
constructor to create // dynamic Employee
object (on heap) emp2 new Employee //
member-selection operator (the dot)
(emp2).setName(Jerry) (emp2).setSalary(900
) // use custom constructor emp3 new
Employee(Mary) // Alternatively, we can
use // dereference-and-select operator -gt
emp3-gtsetSalary(1000) emp3-gtprint() //
delete dynamic objects, delete emp2, emp3
// pointer variables still alive return 0
class Employee public Employee () name
NULL salary 0.0 Employee (string
inName) name inName salary 0.0
void setName(string inName) name inName
string getName() return name void
setSalary(double inSl) salary inSl
double getSalary() return salary
void print() cout ltlt Name ltlt name
ltlt Salary ltlt salary ltlt endl
protected string name double salary
12Pointer Fields
// student.h class Student public
Student() void setID(int inID) int
getID() Student() // destructor
private int id // declare pointer
// student.cpp include student.h StudentStud
ent() id new int // create dynamic
variable void StudentsetID(int inID) id
inID // use dynamic variable int
StudentgetID() return id StudentStuden
t() delete id // delete dynamic variable
int main() Student stu
stu.setID(1234) cout ltlt The ID is ltlt
stu.getID() return 0
13Dynamic Arrays
- GO OVER NOTES ON ARRAYS
- Dynamic Arrays
- int dynArrdynArr can be a pointer to either a
single int or to an array of integers. - dynArr new int 5
- creates an array of 5 (dynamic) integer type
variables and stores in dynArr a pointer to the
zero-th element in this array.
dynArr
14The Index Operator, operator
- Random-access any item in an array can be
accessed or modified immediately, given the index
of the item - for (int i 0 i lt 5 i)
- cin gtgt dynArr i
- Is used to reference the individual items
- dynArr 0 3This is equivalent
to dynArr 3 - In general, for any array a and non-negative
integer i, - ai is equivalent to (a i), e.g.,
- dynArr1 8 is the same as (dynArr 1) 8
15Dynamic Allocation
- A regular arrays capacity is fixed once created
- But for a dynamic array, we can specify the size
as follows - int capacitycin gtgt capacityint dynArr
new int capacity - Note that the capacity need not be known until
run time.
16Destroy A Dynamic Array
- To Destroy A Dynamic Array the pointer point to
(NOT the pointer itself!!!) - To deallocate the space for an dynamic array,
use an empty index - delete dynArr
- Let pointer dynArr point to a new resized array
- capacity 2 // double the
capacity dynArr new int capacity
17Container Classes
- A container is an object that consists of a
collection of items. - For example, an array is a container.
- A container class is a class whose objects are
containers. - There are two widely used kinds of structures for
storing the items in a container object - An array and a linked structure.
- In the first structure, one of the fields in the
class is an array, and the items are stored in
this array. - Advantage allows random-access of items.
- Drawback large-scale movement of items for
inserting, deleting, and resizing (due to fixed
size). - There will be methods to handle movement of
items, but even so, execution speed may be slow.
18Container Classes
- Another way to store a container is in a linked
structure - each item has an associated link that is, a
pointer to the next item in the container.
12
51
27
- Linked Class
- To give you a feel for a linked structure, we now
design and implement a toy class, Linked. - We start with a users view
- Instead of restricting the class to work with
just one type of item, we will let the user
select the item type when the user defines the
container object.
19Class Templates
- To allow this, we will define a template, or
mold, that will allow the definition, at
compile-time, of a container class of some fixed
type. - The container class is a template class, and the
given type is a template argument.
- template ltclass Tgtclass Linked
- ...
-
- T may be any type double, int, Employee, Student
and so on. - For example, a user can defineLinkedltstringgt
wordsLinkedltdoublegt salariesLinkedltEmployeegt
employees
20Review of Function Templates
CSCI 1010 notes
21Why use function templates
CSCI 1010 notes
- int Max (int a, int b)
-
- if (a gt b)
- return a
- return b
-
- How can we write it for any data type?
- All we need to do is change int in 3 places
- C lets us use int as an argument to a
generic function that produces the code for
different data types in actual functions - Using Cs template construct
- Passing it int as an argument for those three
places
22How Do We Do That?
CSCI 1010 notes
- By Using the C template Construct
- Before any function we want to be generic,
put template ltclass Tgt - T is the name of the parameter to the generic
function - Write the function, replacing the desired data
type with T (or whatever name you want) - template ltclass Tgt
- T Max (T a, T b)
-
- if (a gt b)
- return a
- return b
-
23One More Detail
CSCI 1010 notes
- We forgot about the function declaration
- It has to be the same as the definitions header
- So, it has to have that template ltclass Tgt, too
- The declaration looks like this template ltclass
Tgt T Max (T a, T b) - How does C do that?
- Makes a text copy of the templated function
- Substitutes the type argument in the function
call into the type parameter in the function
defn. - Then compiles the resulting code
Note no semicolon
24CSCI 1010 notes
- Contains
- Declaration of templated function Max
- main () function used to test templated function
Max - Definition of function Max
- Note in main () how Max is called
- No differently than before
- BUT it works with any data type
- Even string
- Whats the restriction on whether that Max will
work? - Operator gt must be defined for the argument
data type - For built-in types and library classes, thats a
given - For classes you write yourself, you have to make
sure of it - Exercise T Sum (T a, T b)
25Methods in the Linked class
- To construct an empty Linked object
- To return the number of items currently stored in
a Linked object - To insert an item at the front of a Linked object.
- // Postcondition this Linked object is empty,
that is,// it contains
no items.Linked( ) - // Postcondition the number of items in this
Linked// object has been
returned.long size( ) - // Postcondition newItem has been inserted at
the// front of this
Linked object.void push_front (const T
newItem)
26struct node
item next
- struct Node T item // T is the
template parameter - Node next
-
- The only fields in the Linked class are Node
head // points to first node long length //
number of items in the container - So head is the gateway to the entire container!
27Default Constructor And The size Method
- Linked( ) head NULL
- length 0 // default constructor
- long size( ) return length // method size
28Example
- Linkedltstringgt sneakerList
- sneakerList.push_front (Nike)
- sneakerList.push_front (Adidas)
item next item next
head
Adidas
Nike
NULL
length
2
29Creating a Linked object (list)
Linkedltstringgt sneakerList
length
head
NULL
0
30Inserting an item
sneakerList.push_front (Nike)
newHead
length
head
NULL
0
?
?
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
31Inserting an item
sneakerList.push_front (Nike)
newHead
length
head
NULL
0
?
Nike
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
32Inserting an item
sneakerList.push_front (Nike)
newHead
length
head
NULL
0
Nike
NULL
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
33Inserting an item
sneakerList.push_front (Nike)
newHead
length
head
1
Nike
NULL
- // Postcondition A node with newItem has been
inserted at the front of the Linked container.
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
34 sneakerList.push_front (Adidas)
newHead
?
?
length
head
1
Nike
NULL
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
35 sneakerList.push_front (Adidas)
newHead
?
Adidas
length
head
1
Nike
NULL
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
36 sneakerList.push_front (Adidas)
newHead
Adidas
length
head
1
Nike
NULL
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
37 sneakerList.push_front (Adidas)
newHead
Adidas
length
head
2
Nike
NULL
void push_front (const T newItem) Node
newHead new Node newHead -gt item
newItem newHead -gt next head head
newHead length
38Deleting an Item
- // Precondition this Linked container is
not empty.// Postcondition the front item has
been deleted from this Linked container -
- void pop_front() Node oldHead head
head head -gt next delete oldHead //
deallocates oldHead --length
39Deleting an Item
sneakerList.pop_front( )
oldHead
length
head
2
Nike
NULL
Adidas
void pop_front() Node oldHead head
head head -gt next delete oldHead //
deallocates oldHead --length
40Deleting an Item
sneakerList.pop_front( )
oldHead
length
Adidas
head
2
Nike
NULL
void pop_front() Node oldHead head
head head -gt next delete oldHead //
deallocates oldHead --length
41Deleting an Item
sneakerList.pop_front( )
oldHead
?
length
head
1
Nike
NULL
void pop_front() Node oldHead head
head head -gt next delete oldHead //
deallocates oldHead --length
42Destructor
- // Postcondition This Linked object is
empty, and the space occupied by //
this Linked object has been
deallocated.Linked() while (head !
NULL) pop_front( )
43Destructor
- Destructor is automatically called when the
object goes out-of-scope, that is, when the
object is no longer accessible. - // function sample
- void sample( ) Linkedltdoublegt
weights - int main( ) sample( ) return 0
- At the end of the execution of the function
sample, the linked object weights is
out-of-scope, so its destructor is automatically
called.
44Iterators
- An iterator is an object that enables a user to
loop through a container without violating the
principle of data abstraction. - The Linked and Iterator classes together must
provide a user with the ability to do at least
the following - Start at the beginning of the container
- Determine when no more loop iterations are
possible, e.g., at the end - Advance to the next item in the container
- Return the item where the iterator is now
positioned.
45The Linked Class
- Provide the following two methods
- // Postcondition An Iterator positioned at
the front of this //
Linked container has been returned.Iterator
begin( ) - // Postcondition An Iterator positioned just
beyond the last item //
in this Linked container has been
returned.Iterator end( )
46The Embedded Iterator Class
- // Postcondition true has been returned if itr
is equal to this Iterator.//
Otherwise, false has been returned.bool
operator (const Iterator itr) const - // Postcondition true has been returned if itr
is not equal to this Iterator. - // Otherwise, false has been
returned.bool operator! (const Iterator itr)
const - // Precondition This Iterator is positioned at
an item.// Postcondition The item this Iterator
is positioned at has been returned.T
operator( ) const - // Precondition This Iterator is positioned at
an item.// Postcondition This Iterator has
advanced to the next item unless this Iterator
// was positioned at
the back item in the Linked container before this
call. // In that case,
this Iterator is positioned just beyond the back
item.Iterator operator (int) //
post-increment operator
47Example
- Now a user can iterate through a Linked
container - Linkedltstringgt sneakerList
- sneakerList.push_front(Nike)
- sneakerList.push_front(Adidas)
- LinkedltstringgtIterator itr for (itr
sneakerList.begin( ) itr ! sneakerList.end( )
itr) - if (itr Adidas) cout ltlt
Found Adidas! if ((itr).length() 4)
cout ltlt Found a 4-letter words. -
48Design and Implementation of the Iterator Class
- templateltclass Tgtclass Linked
protected struct Node T
item Node next - Node head long length
- public class Iterator friend class
LinkedltTgt - protected
- public // class Iterator // class
Linked
49Construction
- The Iterator class will have one field a pointer
to the node where the Iterator object is
positioned Node nodePtr
- // Postcondition This Iterator has been
initialized through newPtr.// constructor with
pointer parameter Iterator (Node newPtr)
nodePtr newPtr - This constructor is protected because users know
nothing of Node. Therefore, to allow users to
construct an Iterator object, there is a public
default constructor - // Postcondition This Iterator has been
constructed. Iterator( )
50Definitions of ,!, AND
- bool operator (const Iterator itr)
const return nodePtr itr.nodePtr - bool operator! (const Iterator itr)
const return nodePtr ! itr.nodePtr - T operator( ) const
- return nodePtr -gt item
51operator (int)
- Here is one of several ways to define operator
(int), the post-increment operator. - We construct a temporary iterator through
nodePtr, advance nodePtr to point to the next
node, and then return the temporary iterator.
Iterator operator (int) Iterator itr
(nodePtr) nodePtr nodePtr -gt next return
itr
- Textbook Page 51 52 shows another way to define
it.