Uploaded by Eddie Z

Lec4C++Linked

advertisement
LinkedList Class
Linked List
• Member functions: add, clear, get, insert, isEmpty, remove, size, toString
• LinkedList instance variables:
• pointer to list, i.e., pointer to front node
• front is NULL if list is empty
• int data value
LinkedList
front
add(value)
insert(index, value)
remove(index)
size()
ListNode
13
13
13
NULL
ListNode struct (LinkedList.h)
#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H
struct ListNode {
int data;
ListNode* next;
ListNode(int d = 0, ListNode* ptr = NULL) {
data = d;
next = ptr;
}
};
LinkedList Class (LinkedList.h)
class LinkedList {
public:
LinkedList();
~LinkedList(); // destructor
void add(int value);
void clear();
int get(int index) const;
void insert(int index, int value);
bool isEmpty() const;
void remove(int index);
void set(int index, int value);
int size() const;
friend ostream& operator <<(ostream& out, LinkedList& list);
private:
ListNode * front;
};
#endif
LinkedList Class (LinkedList.cpp)
// Construct a new empty list
LinkedList::LinkedList() {
front = NULL;
}
add Method
// Add new value to the end of the list
void LinkedList::add(int value) {
if(front == NULL) {
front = new ListNode(value);
}
else {
ListNode* cur = front;
while(cur next != NULL) cur = curnext;
cur->next = new ListNode(value);
}
}
get Method
// Returns value at given index in list (first node at index 0).
// Throws integer exception if specified index is not in the interval [0,size-1]
int LinkedList::get(int index) const {
if(index < 0 || index >= size()) throw index;
ListNode* cur = front;
for(int i = 0; i < index; i++) cur = cur->next;
return cur->data;
}
Exercise:
// Sets value in ith node in the list to specified value.
// Throws integer exception if specified index is not in interval [0, size-1].
void LinkedList::set(int index, int value) {
insert Method
// Insert specified value at specified index in list.
void LinkedList::insert(int index, int value) {
if(index < 0 || index >= size()) throw index;
if(index == 0) {
ListNode* list = front;
front = new ListNode(value);
front  next = list;
}
else {
ListNode* cur = front;
for(int i = 0; i < index-1; i++) cur = cur  next;
// add new node after cur
ListNode* newNode = new ListNode(value);
newNode  next = cur  next;
cur  next = newNode;
}
}
remove Method
// Remove value at specified index from the list.
void LinkedList::remove(int index) {
if(index < 0 || index >= size()) throw index;
ListNode *temp;
if(index == 0) {
temp = front;
front = front  next;
}
else {
ListNode* cur = front;
for(int i = 0; i < index-1; i++) cur = cur next;
temp = curnext;
cur  next = temp  next;
}
delete temp;
}
clear Method
// Remove all values from the list.
void LinkedList::clear() {
while(front != NULL) remove(0);
}
Destructor
• Destructor should free all nodes in the list
LinkedList::~LinkedList() {
clear();
}
• A default constructor is provided. But it will not delete the nodes in
the linked list that front points to.
Destructors, Copy Constructors &
Copy Assignment Operators
Non-Default Destructor
When do you need it?
• Memory is allocated in your constructor: use a destructor to delete it.
• Otherwise: memory leaks
Copy Constructor & Copy Assignment Operator
• Two ways to copy an object:
• copy constructor: create a new object that's a copy of an existing object
• copy assignment operator: set an existing object equal to another object
• For existing Person object p:
• Copy constructor:
• Person p2(p); // create new object p2 using state of existing object p
• Or equivalently: Person p2 = p;
• Copy assignment operator:
• Person p2 = ...;
• p2 = p; // p2 is a Person object, and we want to set its state equal to that of p
• If we don't define them in our classes, we get a default destructor, copy constructor
and copy assignment operator.
• When do we need to define our own? If an object has pointers or some other runtime allocation of a resource (e.g., opening a file).
• default copy constructor and assignment operator will do a shallow copy
• default destructor will not deallocate memory allocated for an instance variable
Example
class String {
private:
char* str;
int length;
public:
String(const char* str = NULL); // constructor
~String();
String(const String&); // copy constructor
// other member functions...
};
Shallow Copy
• Default assignment operator and copy constructor produce a shallow
copy
String s1("hello");
String s2 = s1; // default copy constructor invoked
s1
s2
str
length
str
length
5
'h'
'e'
'l'
'l'
5
'o'
'\0'
Default Destructor
• Default destructor does not free the heap-allocated array that the str
instance variable points to
String* s1 = new String("hello");
delete s1; // default destructor results in memory leak
s1
str
length
5
'h'
'e'
'l'
'l'
'o'
'\0'
Example
String::String(const char *s) {
length = strlen(s);
str = new char[length+1];
strcpy(str, s);
}
String::~String() {
delete [] str;
}
// copy assignment operator
String& String::operator =(const String &s){
// copy constructor
if(this != &s) {
delete[] str;
String::String(const String& oldStr){
length = s.length;
length = oldStr.length;
str = new char[length];
str = new char[length+1];
strcpy(str, s.str);
strcpy(str, oldStr.str);
}
}
return *this;
}
Copy Constructor & Copy Assignment
• To avoid implementing them, you can declare them to be private in your
class.
• Then if a client attempts to invoke them, they get a compile error.
• The Rule of Three is a rule of thumb for C++: if your class needs to define any
of copy constructor, assignment operator, destructor, then it needs all three
of them.
Exercise
• Add copy constructor and copy assignment operator to LinkedList class
Download