将值传递给自定义分配器

时间:2017-08-15 20:22:05

标签: c++ memory-management

我正在尝试构建一个自定义分配器来从我自己的数据池中分配。 我从Microsoft站点的一些示例代码开始,这些代码似乎是自定义分配器的最小实现。

来自https://msdn.microsoft.com/en-us/library/aa985953.aspx的原始代码:

template <class T>  
struct Mallocator  
{  
    typedef T value_type;  
    Mallocator() noexcept {} //default ctor not required by STL  

    // A converting copy constructor:  
    template<class U> Mallocator(const Mallocator<U>&) noexcept {}  
    template<class U> bool operator==(const Mallocator<U>&) const noexcept  
    {  
        return true;  
    }  
    template<class U> bool operator!=(const Mallocator<U>&) const noexcept  
    {  
        return false;  
    }  
    T* allocate(const size_t n) const;  
    void deallocate(T* const p, size_t) const noexcept;  
};  

template <class T>  
T* Mallocator<T>::allocate(const size_t n) const  
{  
    if (n == 0)  
    {  
        return nullptr;  
    }  
    if (n > static_cast<size_t>(-1) / sizeof(T))  
    {  
        throw std::bad_array_new_length();  
    }  
    void* const pv = malloc(n * sizeof(T));  
    if (!pv) { throw std::bad_alloc(); }  
    return static_cast<T*>(pv);  
}

template<class T>  
void Mallocator<T>::deallocate(T * const p, size_t) const noexcept  
{  
    free(p);  
}  

我需要在分配器中添加状态,我正在构建它。

我从根本上已经完成了所有功能,但对我是否做过“适当的”事情有疑问。方式。

修改后的代码:

template <class T>  
struct Mallocator  
{  
    typedef T value_type;  
    Mallocator() noexcept {} //default ctor not required by STL

1 - 添加了此构造函数以传入指向我的分配器的指针...

    Mallocator(my_allocator* cust_alloc) noexcept : _cust_alloc(cust_alloc) {}

    // A converting copy constructor:  
    //template<class U> Mallocator(const Mallocator<U>&) noexcept {}

2 - 修改复制构造函数......

    template<class U> Mallocator(const Mallocator<U>&src) noexcept 
    {
        // this does not work:
        // _cust_alloc = src._cust_alloc;

        // this seems ugly, but does work...
        _cust_alloc = const_cast<Mallocator<U>&>(src).custom_allocator();
    }

    template<class U> bool operator==(const Mallocator<U>&) const noexcept  
    {  
        return true;  
    }  
    template<class U> bool operator!=(const Mallocator<U>&) const noexcept  
    {  
        return false;  
    }  
    T* allocate(const size_t n) const;  
    void deallocate(T* const p, size_t) const noexcept;

3 - 为分配器添加访问器,因为复制构造函数问题...

    my_allocator* custom_allocator(){ return _cust_alloc; }

4 - 添加指向我的自定义分配器的指针...

private:
    my_allocator *_cust_alloc;

};  

5 - 在这里调用我的分配器,而不是malloc ...

template <class T>  
T* Mallocator<T>::allocate(const size_t n) const  
{  
    if (n == 0)  
    {  
        return nullptr;  
    }  
    if (n > static_cast<size_t>(-1) / sizeof(T))  
    {  
        throw std::bad_array_new_length();  
    }  

    void* const pv = _cust_alloc->allocate(n * sizeof(T));
    if (!pv) { throw std::bad_alloc(); }  
    return static_cast<T*>(pv);  
}

6 - 在此处调用我的分配器以释放...

template<class T>  
void Mallocator<T>::deallocate(T * const p, size_t) const noexcept  
{  


    _cust_alloc->deallocate(p);
//        free(p);  
}  

虽然这一切都在这一点上起作用,但我对是否可以或应该采取不同的行动有疑问。

问题1 - 我发现我需要将我的成员变量添加到复制构造函数中。这导致在私有时访问我的成员变量的问题。我最初发现这个不寻常,但我错过了复制构造函数使用&#39; U&#39;而不是&#39; T&#39;。我假设(正如原始代码中的注释可能表明的那样)我在这里从一个不同类型的分配器复制,这意味着我正在复制一个不同的类,这解释了为什么我不能&#39;# 39,见&#39;私人会员直接。为了解决这个问题,我添加了一个访问器并对其进行了const_casted。这感觉很麻烦,我很想把成员变量公之于众。有没有更好的方法来形成这部分代码?解释&#39; T&#39;和&#39; U&#39;可能也会有所帮助。

问题2 - 在我写这篇文章时的研究中,我注意到了移动构造函数,完美转发等的参考资料。我不太熟悉,不知道创建和编写移动构造函数的细微差别。此外,我不知道是否需要一个,除非默认移动构造函数没有移动我的私有成员变量的问题。我不确定是否或何时在STL容器的上下文中调用移动构造函数。

在我正在做的事情的背景下,需要这样的东西,它是如何正确形成的?

template<class U> Mallocator(const Mallocator<U>&& src) noexcept
{
    return std::forward<U>(src);
}

问题3 - 总的来说,是否有一些被接受的&#39;如何添加状态&#39;一个比我更好的自定义分配器? (我在这里完全错过了,还是我在正确的轨道上?)

0 个答案:

没有答案