FAQ 30.11 Are there any C classes that help manage remote ownership?

FAQ 30.11 Are there any C++ classes that help manage remote ownership?

graphics/new_icon.gif

Yes, auto_ptr.

The standard template class auto_ptr<T> is a partial solution to managing remote ownership. auto_ptr<Fred> acts like a Fred*, except the referent (the Fred object) is automatically deleted when the auto_ptr dies. auto_ptr<T> is known as a managed pointer.

Managed pointers are useful whenever a referent is allocated by new and when the owner of the pointer owns the referent. In other words, auto_ptr<T> is useful for managing remote ownership.

The most important issue isn't that auto_ptr<T> saves the one line of delete code. The most important issue is that auto_ptr<T> handles exceptions properly: the referent is automagically deleted when an exception causes the auto_ptr<T> object to be destructed. In the following example, class Noisy throws exceptions randomly to simulate the fact that we can't always predict when an exception is going to be thrown (hopefully your classes don't have this property).

Here is a function that randomly returns true and false with 50 50 probability:

 #include <memory> #include <iostream> #include <cstdlib> #include <ctime> using namespace std; bool heads()    //Coin-toss: true with 50 50 probability { return (rand() >> 4) % 2 ? true : false; } 

Here is a class that prints messages and possibly throws exceptions in its functions.

 class Noisy { public:   Noisy() throw();  ~Noisy() throw();   void g() throw(int);   friend void h(Noisy& n) throw(int);   Noisy& operator= (const Noisy&) throw();   Noisy            (const Noisy&) throw(); }; Noisy::Noisy() throw()   { cout << "Noisy::Noisy(); "; } Noisy::~Noisy() throw()   { cout << "Noisy::~Noisy(); "; } void Noisy::g() throw(int)   { cout << "Noisy::g(); "; if (heads()) throw 5; } void h(Noisy& n) throw(int)   { cout << "h(Noisy&); "; if (heads()) throw 7; } 

Here is a function that wisely chooses to use the managed pointer auto_ptr<Noisy>.

 void usingManagedPointers() throw(int) {   cout << "using an auto_ptr<Noisy>: ";   auto_ptr<Noisy> p(new Noisy());   p->g();   h(*p);   cout << "didn't throw\n"; }                                                    <-- 1 

(1) The delete is automagic (no need to worry)

Here is the same function, but this time using a raw Noisy* pointer. Note how much more complex this code is, even though it is doing the same thing. A significant portion of this code exists solely to ensure that the referent is deleted properly, whereas in the previous example the managed pointer enabled most of this scaffolding to disappear.

 void usingRawPointers() throw(int) {   cout << "using a Noisy* pointer: ";   Noisy* p = new Noisy();   try {     p->g();     h(*p);   }   catch (...) {     delete p;     throw;   }   delete p;                                          <-- 1   cout << "didn't throw\n"; } 

(1) Here the delete is explicit

Here is main() that repeatedly calls the foregoing routines.

 int main() {   srand(time(NULL));   // Randomize the random number seed   for (int i = 0; i < 10; ++i) {     try {       usingRawPointers();       usingManagedPointers();     } catch (int i) {       cout << "caught " << i << '\n';     }     cout << '\n';   } } 


C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net