Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

How to use the classes of Mango-ptr

This page discusses the use of Owned<P*> and other classes via some examples and issues to consider when using them.

Examples

Basic example

The documentation page for each class also has examples of use. Here is a code example where a class A is an owner of a B* and class C is simply a user of the B* that is owned by the A. The B* will automatically die at the same time as the A, thereby invalidating the pointer held in C. But the C is able to check whether the B* still exists before calling its methods:

    struct B { 
        void method() {}
        void constMethod() const {}
    };

    class A {
        // like a B*, but will be automatically 
        // destroyed when A destroyed:
        Owned<B*> _ptr; 

        public:
        // initialize ptr with new B
        A(): _ptr(new B) {}
    };

    class C {
        // like a const B*, but C just uses the pointer
        BLink<const B> _ptr;

        C(const BLink<const B>& p): _ptr(p) {}
        void test() const {
            assert(_ptr()->isNotNull());
            _ptr()->method(); // compile error, B is const
            _ptr()->constMethod(); 
        }
    };

    int main() {
        A a;
        C c(a._ptr); 
        c.test(); // ok

        A a2 = a; // deep copy of A::_ptr will occur automatically
    }
    // B objects in a and a2 automatically deleted

Here is an example of using an owned container. Class A has a list of pointers, which would normally require a destructor and a loop over all elements of the list to call delete on each. By using the Owned container, it doesn't have to worry about those memory management issues. Note how the container that is passed to the outside of A is the list itself rather than the owned list. This is recommend for this situation since the fact that the list is owned is an implementation detail to outsiders.

    class A {
        typedef std::list<int*> List;
        Owned<List> list;
        
        public: 
            A() { ... populate list...}
            const List& getList() const {return list.cntr();}
    };

Idiomatic examples

Look at the files tests/testIdiom*.cc for various simple implementations of common patterns that illustrate some of the idioms important to C++. They are included here for your convenience:

Usage

Normal Usage

Owned pointers with STL containers

STL containers use value-based semantics. This will usually lead to expensive copy and assignment operations during operations on the containers. Often, such operations are undesirable because they are costly for the type of object stored, either in time, memory, or some other resource. Using containers of pointers is often a way of getting around this since pointers are simple, sortable values. However, using a strict Owned pointer in an STL container means the pointers are again considered as values, which defeats the purpose of using pointers in the first place.

This is an example of how the current STL containers are not very well suited for objects that should not be copied inside the container. Another consequence of this is that many algorithms on the STL containers currently do not work optimally when the element type is an Owned pointer. or BLink. This is because many algorithms use std::swap and std::iter_swap, but problems with namespace resolution mean that even if you overload std::swap, it is likely not to be found. Overloading iter_swap is complicated and error-prone. Therefore, you should use Owned<Container> instead of pure STL containers.

There are tricks you can use if you really want to store strict Owneds in STL containers, if you won't be doing any re-ordering of the container elements. You can create an empty Owned at a known place of the container (say the back), and only after that assign your dynamic object to it:

    std::list<MangoPtr::Owned<T> > owners; // list of strict owners
    owners.push_back( MangoPtr::Owned<T>() ); // empty owner
    owners.back().takeOwnership( new T );
You could create several empty owners at once, then have each take ownership of a newly allocated object. This however does not work with containers that require unique elements, or sort their elements, since all empty owners are the same from STL's perspective.


Generated on Tue Nov 12 20:44:01 2002 for Mango-ptr Library by doxygen1.2.18