Using the auto_ptr concept in C++

In C++, local instances (these not allocated by hand) have their destructors run as soon as they go out of scope. This behavior is explored in a few different schemes, besides its obvious intent of destructing the instance. The most known one is the auto_ptr class, part of the STL. It is merely a memory guard which takes care of deallocating the given pointer once its own scope is over. In the short example below, the s variable won’t leak.

#include <stdlib.h>
#include <memory>
#include <iostream>

using namespace std;

void f()
{
        char *s = strdup("foobar");
        auto_ptr<char> sp(s);
        cout << sp.get() << endl;
}

While this is an interesting place to use this concept, it’s a good algorithm to be aware of generically. A good example of how useful this could be is how the apt-shell (part of APT-RPM) cache guard mechanism was implemented. This program was implemented as a refactoring of apt-get, but they have a fundamental difference: while apt-get is a one-shot program (run just once, and get back to the user), apt-shell maintains the internal cache (the structure where information about the packages is kept) alive for a long time, and changes it in many different ways during its execution time. Thus, I had to implement some way to make it easy to protect this cache against being unadvisedly changed in all these functions coming from apt-get. To do that, I have implemented an AutoRestore class which takes care of restoring the original state of the cache, unless explicitly told to release it. Here is the complete class, from apt-shell.cc:

class AutoRestore
{
   pkgDepCache::State State;
   bool Guarded;
   public:
   inline pkgDepCache::State *operator ->() {return &State;};
   inline pkgDepCache::State *operator &() {return &State;};
   inline void UnGuard() { Guarded = false; };
   AutoRestore(pkgDepCache &Cache)
      : State(&Cache), Guarded(true) {};
   ~AutoRestore() { if (Guarded) State.Restore(); };
};

To use it, it’s just a matter of creating a local instance, passing the cache to the constructor. It will take care of undoing unexpected changes. Really comfortable!

This entry was posted in C/C++. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *