none
关于自定义Allocator的问题? RRS feed

  • 问题

  • 我想看一下STL容器类是如何管理其内存的,如何时分配、释放内存。于是我写了一个MyAllocator类,继承自std::allocator,所有的函数实现都是打印一行信息,然后调用相应的基类函数。代码如下:

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <memory>
    
    
    template <typename T>
    class MyAllocator : public std::allocator<T> {
    	typedef typename std::allocator<T> 			BaseType;
    	typedef typename BaseType::size_type		size_type;
    	typedef typename BaseType::pointer			pointer;
    public:
    	MyAllocator()
    	{ printf( "MyAllocator Constructor.\n" );}
    	MyAllocator( const MyAllocator &rhs )
    	{printf( "MyAllocator Copy Constructor.\n" );}
    	~MyAllocator()
    	{ printf( "MyAllocator Destructor.\n" );}
    
    	pointer allocate( size_type _Count, const void* _Hint )
    	{
    		printf( "MyAllocator::allocate() count = %u, hint = %x\n", _Count, _Hint );
    		return BaseType::allocate( _Count, _Hint );
    	}
    	
    	void deallocate( pointer _Ptr, size_type _Count	)
    	{
    		printf( "MyAllocator::deallocate() ptr = %x, count = %u\n", _Ptr, _Count );
    		BaseType::deallocate( _Ptr, _Count );
    	}	
    	
    	void construct( pointer _Ptr, const T &_Val )
    	{
    		printf( "MyAllocator::construct() ptr = %x\n", _Ptr );
    		BaseType::construct( _Ptr, _Val );
    	}
    
    	void destroy( pointer _Ptr )
    	{
    		printf( "MyAllocator::destroy() ptr = %x\n", _Ptr );
    		BaseType::destroy( _Ptr );
    	}
    };
    
    
    struct Test {
    	Test()
    	{ printf( "Test Constructor.\n" ); }
    	
    	Test( const Test &rhs )
    	{ printf( "Test Copy Constructor.\n" ); }	
    	
    	~Test()
    	{ printf( "Test Destructor.\n" ); }	
    	
    	int x;
    };
    
    class MyString : public std::basic_string< char, std::char_traits<char>, MyAllocator<char> > {
    
    };
    
    template <typename T>
    class MyVector : public std::vector< T, MyAllocator<T> > {
    
    };
    
    int main()
    {	
    	// MyVector test
    	{
    		MyVector<int> vec;
    		vec.reserve(100);
    		vec.push_back(1);
    		vec.push_back(2);
    		printf( "%u, %u\n", vec.size(), vec.capacity() );
    	}
    
    	// MyString test
    	{
    		MyString s;
    		s.append("Hello, world!" );
    	}
    	
        return 0;
    } 

    本想在调用MyVector的reserve或push_back函数时, MyAllocator的allocate函数会被调用,会看到其输出信息,但是事与愿违。程序运行结果如下:

    MyAllocator Constructor.
    MyAllocator Copy Constructor.
    MyAllocator Destructor.
    MyAllocator Destructor.
    2, 100
    

    只有MyAllocator的构造和析构函数被调用,且都是因为MyVector的创建而引起,MyString虽然也指定了MyAllocator为其内存分配器,但并未引发MyAllocator的任何动作。

    还有一点很奇怪,所有的MyAllocator对象都在调用reserve和push_back之前销毁了,似乎MyVector并未使用MyAllocator作为内存分配器。

    这到底是什么原因呢???

    2013年5月31日 9:07

答案

  • 不需要从stl::alloctor派生。

    template<class T>
    inline T* _allocate(ptrdiff_t size, T*)
    {
    	
    	T* tmp = static_cast<T*>(malloc(size * sizeof(T)));
    	if ( tmp == 0 )
    	{
    		exit(1);
    	}
    	return tmp;
    }
    template<class T>
    inline void _deallocate(T* buffer)
    {
    	free(buffer);
    }
    template<class T1, class T2>
    inline void _construct(T1* p, const T2& value)
    {
    	new(p) T1(value);
    }
    template<class T>
    inline void _destroy(T* ptr)
    {
    	ptr->~T();
    }
    template<class T>
    class MyAllocator  
    {
    public:
    	typedef T    value_type;
    	typedef T*   pointer;
    	typedef const T* const_pointer;
    	typedef T&     reference;
    	typedef const T& const_reference;
    	typedef size_t size_type;
    	typedef ptrdiff_t difference_type;
    	template <class U>
    	struct rebind
    	{
    		typedef MyAllocator<U> other;
    	};
    	static pointer allocate( size_type n, const void* hint = 0)
    	{
    		return _allocate(static_cast<difference_type>(n),  static_cast<pointer>(0))	;
    	}
    	static void deallocate(void* p, size_type n)
    	{
    		_deallocate(p);
    	}
    	void construct(pointer p, const T& value)
    	{
    		_construct(p, value);
    	}
    	void destroy(pointer p)
    	{
    		_destroy(p);
    	}
    	pointer address(reference x)
    	{
    		return static_cast<pointer>(&x);
    	}
    	char *_Charalloc(size_type n) {
    		return  _allocate(static_cast<difference_type>(n),  static_cast<char *>(0))	;
    	} 
    	const_pointer const_address(const_reference x)
    	{
    		return static_cast<const_pointer>(&x);
    	}
    	size_type max_size() const
    	{
    		return size_type(UINT_MAX/sizeof(T));
    	}
    public:
    	MyAllocator(){};
    	virtual ~MyAllocator(){};
    };


    麻烦把正确答案设为解答。

    2013年6月3日 3:34
    版主