On Fri, 19 Dec 2003 09:27:23 +0800, "Darkay Li"
<darkay_li@hotmail.com> wrote:
[color=blue]
>I have try to create an allocator like follow:
> // the type of allocator must be some kind of pointer
> template <class Type>
> class PointerAllocator : public std::allocator<Type>
> {
> public:
> typedef std::allocator<Type> BaseClass;
>
> public:
> void destroy(pointer ptr)
> {
> delete (*ptr); // "Type" must be a pointer of object
> BaseClass::destroy(ptr);
> }
> };
>
>My allocator derive from the std::allocator, and just rewrite the destroy
>method, to delete the object which the pointer pointer at.[/color]
What makes you think that your destroy member will be called? If you
allocator is rebound, the rebound type will be a std::allocator, not
your allocator, and hence your destroy won't be used.
In fact, your allocator doesn't conform to allocator requirements:
Alloc::rebind<U>::other::rebind<T>::other has to be the same as Alloc
(for T). This isn't the case with yours, hence the problems.
[color=blue]
>and then I create three containers:
> template <class Type>
> class PointerList : public std::list<Type, PointerAllocator<Type> >
> {
> };
>
> template <class Type>
> class PointerDeque : public std::deque<Type, PointerAllocator<Type> >
> {
> };
>
> template<class Key, class Type, class Traits = less<Key> >
> class PointerMap : public std::map<Key, Type, Traits,
>PointerAllocator<Type> >
> {
> };
>These container can store pointer of the object and free the object it self.[/color]
Did you actually test this? You may find that your destroy member is
never called.
[color=blue]
>
>at last I write my test code:
>int main(int argc, char* argv[])
>{
> PointerDeque<int *> pd;
> pd.push_back(new int(10));
> int *p = pd.front();
> cout << *p << endl;
>
> PointerList<int *> pl;
> pl.push_back(new int (10));
> cout << **pl.begin() << endl;
>
> PointerMap<int , int *> pm;
> pm[1] = new int(10);
> cout << *pm[1] << endl;
>
> return 0;
>}
>everything OK when I using VC6 and SGI's STL(both VC6 and VC7.1),[/color]
When you say ok, was your destroy function actually called?
but when I[color=blue]
>compile the test code with VC7.1(P.J STL) I got error (error message show in
>the end). I check the error and find it's the problem of deque's iterator.
>In VC7.1 the iterator of deque definition is:
> class iterator
> : public const_iterator
> { // iterator for mutable deque
> public:
> //......
> iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
> : const_iterator(_Off, _Pdeque)
> { // construct with offset _Off in *_Pdeque
> }
> }
>the constructor prototype of iterator is :
>iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
>and I find it's different from const_iterator's constructor prototype:
>const_iterator(size_type _Off, const _Myt *_Pdeque)
>
>Why not use the same definiation of const_iterator?[/color]
Well, according to the allocator requirements, _Myt and deque<Ty,
_Alloc> are the same type, so the implementation is allowed to use
them interchangeably.
[color=blue]
>when I modify the constructor of iterator as the same with const_iterator.
>the all my test code compile pass(and run OK).
>Is it the BUG of VC7.1 ?[/color]
No. Your approach isn't going to work. For a start you will have
double deletion problems. Instead I would recommend either writing a
container adapter for pointer holding containers that deletes pointers
when necessary, or use a container<shared_ptr<T> >. e.g.
template <class Cont>
class pointer_container
{
protected:
Cont c;
public:
typedef typename Cont::iterator iterator;
//...
typedef typename Cont::value_type value_type;
void pop_back()
{
delete c.back();
c.pop_back();
}
//etc.
};
Remember that mutating algorithms (like remove_if) will still cause
problems.
Tom
C++ FAQ:
http://www.parashift.com/c++-faq-lite/
C FAQ:
http://www.eskimo.com/~scs/C-faq/top.html