Automatic pointers should be used when the lifetime of the element is the same as the lifetime of the pointer, but when an explicit deletion of the element is awkward or even impossible. This applies in particular to pointers to objects that are dynamically created within a function, and whose lifetime is the scope of the function. The function may be left through several return statements or through an exception being thrown from some other function being called.
Using the assignment operator, the automatic pointer is used to point to another element (which is implicitly a new element). The assigned pointer is set to NULL.
If you define a collection taking automatic pointers as elements, the elements are automatically deleted when the collection is destructed, when an element is removed, or, if the element was not added to the collection, when the variable or temporary holding the pointer is destructed. The following example deletes all pointers that were added previously to the set with the destruction of the set:
#include "person.h" // Declaration of Person class #include <istdops.h> #include <iset.h> typedef IAutoElemPointer<Person> AEPointer; typedef ISet<AEPointer> AddressList; ostream& operator<<(ostream& os,Person A) { return (os << endl << A.GetPersonName() <<" "<<A.GetTNumber()); } void main() { AddressList Business; AddressList::Cursor myCursor1(Business); Business.add(AEPointer (new Person("Peter Black","714-50706"),IINIT)); Business.add(AEPointer (new Person("Carl Render","714-540321"),IINIT)); Business.add(AEPointer (new Person("Sandra Summers","x"),IINIT)); Business.add(AEPointer (new Person("Mike Summers","x"),IINIT)); //The temporary automatic pointer variables were set to NULL //when the pointer was copied to the collection. //The following deletes the second Person ("Sandra ..."), because it //was not added (note that in a set, each element occurs only once). { Business.add(AEPointer (new Person("Sandra Summers","x"),IINIT)); } forICursor(myCursor1) { cout << *Business.elementAt(myCursor1); } }
You should be aware of the implementation details described below when transferring automatic pointers between functions. Consider the following cases:
The following code passes an automatic pointer to a called function and the pointer is returned.
IAutoPointer<Int> someFunc(IAutoPointer<Int> autoIntPtr) { return autoIntPtr; } ... main () { IAutoPointer<Int> myIntPtr(new Int(5), IINIT); cout << *someFunc(myIntPtr) << endl; }
This program results in the following taking place at runtime:
The following code returns an object that has been dynamically created using an automatic pointer.
Int someFunc() { IAutoPointer<Int> autoIntPtr(new Int(6), IINIT); return *autoIntPtr; } ... main() { cout << someFunc() << endl; }
This program results in the following taking place at runtime:
Introduction
to the Collection Classes
Collection
Class Hierarchy
Overall
Implementation Structure
Adding
Elements
Removing
Elements
Replacing
Elements
Smart
Pointers
Choosing the Appropriate
Smart Pointer Class
Constructing Smart
Pointers
Using Element
Pointers
Using Managed
Pointers
Things to Watch Out
For When Using Smart Pointers
Copying and
Referencing Collections
Instantiating the
Collection Classes