If I couldn't use boost::shared_ptr nor equivalent I'd rather make my own
reference counted smart pointer than delete those maps manually.
True. I was going to suggest that too if getting approval is indeed
*that* difficult.
In all likelihood, taking the effort to create a smart pointer is a
good investment.
In case the OP is curious, in order to properly create a shared_ptr-
style smart pointer, you need to make sure that it is "copy-
constructible" and "assignable". Also, you must make sure that the
copy constructor (i.e.
my_shared_ptr<>::my_shared_ptr<>(my_shared_ptr<>&)) and the assignment
operator (my_shared_ptr<>& operator=(my_shared_ptr<>&)) use const
arguments - my_shared_ptr<>::my_shared_ptr<>(const my_shared_ptr<>&)
for example.
Boost doesn't implement it this way (I think), but if I were to
implement a shared_ptr, I would make the shared_ptr a handle to the
object. That is, I would create something like:
my_shared_ptr<T> ---> my_reference_count_ptr<T> ---> T object
(where ---> means "holds a pointer to")
my_reference_count_ptr is responsible for holding the pointer to the
object and keeping a reference count (preferably size_t, so that you
run out of memory before you can cause the count to wrap around). I
would suggest making its constructor private and making my_shared_ptr
a friend of my_reference_count_ptr.
my_reference_count_ptr's only ctor requires a plain old pointer to an
object, It initializes its pointer to the same value as that pointer,
and starts its reference count (I would prefer to init it at zero and
have my_shared_ptr handle incrementing that, but this is personal
preference). Its destructor then deletes whatever pointer it is
holding.
Others will prefer to include a "release" and "acquire" method in the
my_reference_count_ptr, but personally I don't, because I haven't
quite grokked yet what is safe to do after delete(this). If I were to
implement this I'd put them in my_shared_ptr.
When my_shared_ptr is constructed from a plain old pointer, it new's a
my_reference_count_ptr object and stores that into itself. Then it
calls its "acquire" method, which increments the reference count of
its my_reference_count_ptr (setting it to 1). This should be its
default constructor too, so put a default null pointer.
When my_shared_ptr is constructed from another my_shared_ptr
(my_shared_ptr<>::my_shared_ptr<>(const my_shared_ptr<>&)), it copies
the pointer from the input argument. Note that it copies just the
pointer, not the my_reference_count_ptr object itself; this object is
"shared" between the two my_shared_ptr's. Then it calls its acquire
method.
When my_shared_ptr is assigned from another my_shared_ptr
(my_shared_ptr<>& operator=(const my_shared_ptr<>&)), it first calls
its "release" method, which decrements the reference count of its
current my_reference_count_ptr; release then checks if the reference
count is zero, and deletes the my_reference_count_ptr object if so
(which will call the dtor for my_reference_count_ptr, which will
delete the object). Then it copies the pointer from the input
argument and calls its acquire method.
When my_shared_ptr is destructed, it simply calls its release method.
my_shared_ptr should overload the unary * and the -> operators. These
dereference and return, respectively, the pointer of its current
my_reference_count_ptr object.
Test your implementation well; including creating local variables for
it and doing exceptions; create a test class whose destructor has a
visible side effect (std::cout <<"destructor called!\n"
and see if
the destructor is indeed called.
Then you can use my_shared_ptr< map<std::string, std::string> > in
your outer map, and never worry about destructing them again.