Upload
asher-carson
View
217
Download
0
Embed Size (px)
DESCRIPTION
Destructor Member Function Distinguished from a constructor using the ~ before the class name. Responsible for deleting all heap variables. If you use the heap in your class you must have a destructor. One of “The Big Three”: Fall 2015CISC/CMPE320 - Prof. McLeod3
Citation preview
Fall 2015 CISC/CMPE320 - Prof. McLeod 1
CISC/CMPE320• Assignment 4 is due Nov. 20 (next Friday).• SDD document framework should be set up in
your Wiki by now.
• Today:– The Heap, Cont.– Common Memory Issues.– Namespaces.
Fall 2015 CISC/CMPE320 - Prof. McLeod 2
Heap Memory• To return memory to the heap, you must use the delete operator. To free up an array, use delete[]. Supply a pointer to the operator.
• When you use new to create an array the size does not have to be known until run time:
double* a = new double[arraySize];
• The pointer a will reside on the run-time stack, but the array structure will be on the heap.
Destructor Member Function• Distinguished from a constructor using the ~
before the class name.• Responsible for deleting all heap variables.• If you use the heap in your class you must have a
destructor.
• One of “The Big Three”:
Fall 2015 CISC/CMPE320 - Prof. McLeod 3
Fall 2015 CISC/CMPE320 - Prof. McLeod 4
“The Big Three” – Summary• Destructor:
– Frees all heap memory used by the object.• Copy constructor:
– Initializes the object as a copy of the same type object supplied as a parameter. If you are using heap memory you will need to allocate and initialize each value.
• Assignment operator:– Check to make sure that you are not assigning yourself.
If so, do nothing.– Free up the heap memory that is no longer needed.
Copy the value of the argument supplied.– Return *this.
“The Big Three”
• More on these guys later.
• For now, look at some common errors created by improper use of memory in C++.
• Using the heap makes it much easier for the coder to create errors!
Fall 2015 CISC/CMPE320 - Prof. McLeod 5
Fall 2015 CISC/CMPE320 - Prof. McLeod 6
Common Memory Errors• Using a variable that has not been initialized.• Using a pointer to reference a memory location
that is no longer valid.• Forgetting to delete something on the heap.• Deleting a memory value that was never
allocated.• Deleting something on the heap more than once.
• Look at each of these, in turn:
Fall 2015 CISC/CMPE320 - Prof. McLeod 7
Initialization Memory Errors• We’ve seen this one before.
• A variable or pointer is created, but not initialized.• Includes creating an array on the heap, but not
initializing its elements.
• You don’t get an error, you just get some random value – whatever happens to be in that memory location.
Fall 2015 CISC/CMPE320 - Prof. McLeod 8
Lifetime Memory Errors• Seen this one before, too:
• When an activation record is popped off the run-time stack it takes all its local variables with it – they are no longer valid.
• If you have returned a pointer to a local variable, that location will only be valid until the next function invocation occurs.
• It is likely that this location will be overwritten.
Fall 2015 CISC/CMPE320 - Prof. McLeod 9
Lifetime Memory Errors, Cont.• For example:
char* readALine() {char buffer[200];cin >> buffer;return buffer;
}char* p = readALine();
• p is called a “dangling pointer” as it is pointing to memory that is no longer valid after readALine() is finished.
Fall 2015 CISC/CMPE320 - Prof. McLeod 10
Aside – Buffer Overflow Error• Consider that readALine() function again:• Suppose the user entered more than 200
characters:– In this case, the extra characters would end up
being written to memory beyond the dimensions of the array.
– This used to be a popular way for virus writers to inject their own function into an application.
– If you can overwrite the return address of the activation frame to the address of your function…
Fall 2015 CISC/CMPE320 - Prof. McLeod 11
Lifetime Memory Errors, Cont.• You can cause similar behaviour if you attempt to
return a reference to a local variable. For example:
Fraction& operator+(const Fraction& left, const Fraction& right) {
Fraction result(left.numer() * right.denominator() + right.numer() * left.denominator(), left.denominator() * right.denominator()); return result;}
Get rid of this
Fall 2015 CISC/CMPE320 - Prof. McLeod 12
Memory Leaks• When you forget to delete something on the heap.• More likely to cause a problem in a long-running
program.• Suppose you have successive re-assignments to
the same pointer variable inside a loop.• If you don’t carry out a delete in-between
assignments each object remains on the heap.• Eventually the heap manager will be unable to
service any new requests.
Fall 2015 CISC/CMPE320 - Prof. McLeod 13
Invalid Memory References• What happens when you are too eager to delete a
value from the heap.• If you have more than one pointer aliased to that
value, then the second pointer becomes invalid.• For example, deleting the nodes of a linked list in
a for loop:
for (Node* p = ptr; p != NULL; p = p->next)delete p;
}• p->next is no longer accessible after deletion.
Fall 2015 CISC/CMPE320 - Prof. McLeod 14
Aside – Using nullptr• You can assign a pointer to be nullptr. (It does
not happen by default as in Java!).• Deleting a null pointer has no effect.• So, consider setting a pointer to nullptr after
you have deleted it:– This will prevent you trying to invoke any functions from
the pointer (you will get a null pointer error).– And if you do try to delete the pointer again, nothing
bad will happen.
Fall 2015 CISC/CMPE320 - Prof. McLeod 15
Deleting an Un-Initialized Pointer
Fraction* frac;delete frac;
• Bad news. You are trying to delete garbage.• Better to set to nullptr if you cannot initialize
right away:
Fraction* frac = nullptr:delete frac;
Fall 2015 CISC/CMPE320 - Prof. McLeod 16
Object Slicing• Another memory problem that is particular to C++.• For example:
Child* c = new Child(arguments…);Parent* p = c; // OKParent pp = *c; // NOT OK
• This is legal, compiles and runs fine, but what is the problem with the last line?
Fall 2015 CISC/CMPE320 - Prof. McLeod 17
Object Slicing, Cont.• The portion of the Child object that will not fit
into an object of type Parent is “sliced” away – it is lost, when the pointer, c, is de-referenced.
• This is one of the reasons why it is best to access objects through pointers or references only.
Fall 2015 CISC/CMPE320 - Prof. McLeod 18
Polymorphism – Peeking…• A dynamic cast can be used to determine what
kind of object you actually have.• If the cast fails a nullptr is returned.
• For example:Child* c = dynamic_cast<Child*>(object);
• c will be nullptr if object is not a Child or a parent of Child.
Fall 2015 CISC/CMPE320 - Prof. McLeod 19
Peeking, Cont.• Note that a static_cast<Child> will not check
to see if the type will work.• You don’t get a nullptr, you just get a
problem…
• It is best to just use static_cast<type> with primitive types only.
Fall 2015 CISC/CMPE320 - Prof. McLeod 20
More Peeking• The typeid() operator is a more general way of
determining an object’s type.• It is obtained from the <typeinfo> library.• Remember to de-reference a pointer in order to
compare its type.• For example:
if (typeid(*pointer) == typeid(type)) …
Fall 2015 CISC/CMPE320 - Prof. McLeod 21
Back to the Shapes Example• See the Shapes hierarchy
program again, using the heap.
• Somewhat simplified from last time.
• Does not implement the “Big Three”, just the destructor.
• Also includes the use of our own namespace just for yucks!
Shape
colour
Rectangle
width, height
Square
Fall 2015 CISC/CMPE320 - Prof. McLeod 22
Namespaces• We’ve been using namespace std; for a
while now.• Without it, you would need to write:
std::cout << something << std::endl;
• A simple mechanism to avoid naming conflicts.• A class can have the same name as long as it is
in a different namespace.
Fall 2015 CISC/CMPE320 - Prof. McLeod 23
Namespaces, Cont.• To place your class definitions in a namespace,
simply name it:
namespace alpha {class dingdong {…
};}
• Now dingdong can be defined in another namespace (like std) and there will not be a conflict.
Fall 2015 CISC/CMPE320 - Prof. McLeod 24
Namespaces, Cont.• Particularly useful when you are building a library
of classes.• You will want to make sure your namespace’s
name is unique.• You can use an alias to make this easier:
namespace alpha = Alpha_Software_Company;
• Now the user of your library, just needs to type:
alpha::someMethod();
Fall 2015 CISC/CMPE320 - Prof. McLeod 25
Namespaces, Cont.• The only namespace that you should identify with
the using keyword is std.• All other namespaces should be named in the
statement, like alpha::.• Then you won’t conflict with anything in the std
namespace.
Fall 2015 CISC/CMPE320 - Prof. McLeod 26
“The Big Three” Again…• Destructor:
– Frees all heap memory used by the object.• Copy constructor:
– Initializes the object as a copy of the same type object supplied as a parameter. If you are using heap memory you will need to allocate and initialize each value.
• Assignment operator:– Check to make sure that you are not assigning yourself.
If so, do nothing.– Free up the heap memory that is no longer needed.
Copy the value of the argument supplied.– Return *this.
Fall 2015 CISC/CMPE320 - Prof. McLeod 27
Destructor• Sounds sinister!• If you have any attributes that use the heap, you
must have a destructor that cleans them up:
String::~String() {delete[] buffer;
}
Fall 2015 CISC/CMPE320 - Prof. McLeod 28
Destructor, Cont.• Invoked:
– For any local variables when execution reaches the end of the block in which they are declared.
– For any arguments when the end of the function is reached.
– Any temporary (named or unnamed) variables used in a statement when the statement is complete.
– If a variable stored on the heap is deleted (using delete).
– For all global and local static variables when main completes.
– When an object is deleted, for all attributes in the object.
Fall 2015 CISC/CMPE320 - Prof. McLeod 29
Destructor, Cont.• Invoked, cont.:
– When an object from a derived (child) class is deleted, for all attributes in the base (parent) class.
– When an exception is thrown and, as a result, execution leaves the current block of code.
• If you don’t write your own destructor the system-generated one is just an empty destructor – rather useless…
• Only needed if any of your attributes use heap memory. Prevents memory leaks.
Fall 2015 CISC/CMPE320 - Prof. McLeod 30
Aside – Deletion vs. Destruction• Deletion occurs when a pointer is passed to the delete operator.
• Destruction occurs whenever the destructor is invoked.
• A pointer is deleted, an object is destroyed.
• (Remember to set a pointer variable to NULL after you have deleted it…)