All smart pointers have two constructors: a default constructor that initializes the pointer to NULL, and a constructor taking a C++ pointer to an element that you must have created before (using new).
Implicit conversions from a C++ pointer to a managed or automatic pointer are dangerous: elements might be implicitly deleted without your being aware that this has happened. Therefore, the conversion functions for these classes take an extra argument IINIT to make the construction explicit. Hence, the notation for creating a managed or automatic pointer is:
IAutoPointer < E > ePtr (new E, IINIT);
Note: After you have constructed a managed or automatic pointer from a C++ pointer, you should no longer use the C++ pointer. You should only access the element through the pointer of the given class. Otherwise, the element could be implicitly destructed while a C++ pointer still refers to it. In particular, you must not construct two managed pointers or two automatic pointers from the same C++ pointer, because this would cause the managed pointers to keep two separate reference counts, and to implicitly delete the referenced element twice. For example:
IString* s = new IString("..."); IMngPointer < IString > p1 (s, IINIT); // OK IMngPointer < IString > p2 (s, IINIT); // NO! // Do not use s a second time, because the compiler may try to // delete the IString object referred to by s, p1, and p2 twice.
You should keep the following rule in mind when using managed or automatic pointers created from standard pointers: Never use the C++ pointer once the managed or automatic pointer has been created from it, because this may interfere with the automatic storage management. For example, the object that is referenced by a C++ pointer and by an automatic pointer created from this C++ pointer, is deleted as soon as the automatic pointer gets out of scope. The C++ pointer then points to undefined storage.
The extra IINIT argument is introduced to make such situations explicit and especially to avoid the usage of the constructor as an implicit conversion operator. The IINIT argument is defined as follows:
enum IExplicitInit {IINIT};
Introduction
to the Collection Classes
Collection
Class Hierarchy
Overall
Implementation Structure
Flat
Collections
Trees
Smart
Pointers
Choosing the Appropriate
Smart Pointer Class
Using Automatic
Pointers
Using Element Pointers
Using Managed
Pointers
Things to Watch Out
For When Using Smart Pointers
Adding an Element to
a Collection
Removing an Element
from a Collection
Taking Advantage of
the Abstract Class Hierarchy