C ++ 11分配器

Chr*_*isz 5 c++ memory-management allocator c++11

我还没有看到很多关于如何在C ++ 11中创建自定义分配器的好的示例或教程。我确实看到,自C ++ 03起,它已经发生了变化。但是,那时我也不知道该怎么做。

通过尽可能多的信息,我得出了以下结论:

// Project Includes
#include "IMemoryManager.h"

// Standard Includes
#include <cstddef>
#include <iostream>
#include <memory>

//------------------------------------------------------------------------------
/// <summary>
/// A STL compliant custom allocator
///
/// Based on Dr Dobbs article
/// http://www.drdobbs.com/the-standard-librarian-what-are-allocato/184403759
/// I attempted to make it C++11 compliant.
/// Takes an Interface to a Memory Manager which will implement the custom memory management solution.
/// </summary>
template <class T>
class CustomAllocator
{
    std::unique_ptr<IMemoryManager> m_memoryManager;

public:

    typedef T value_type;

    /// Allocator takes ownership of memory manager
    CustomAllocator(std::unique_ptr<IMemoryManager> memoryManager)
        :
        m_memoryManager(std::move(memoryManager))
    {
    }

    ~CustomAllocator()
    {
    }

    CustomAllocator(const CustomAllocator & rhs) = delete;
    void operator =(const CustomAllocator & rhs) = delete;

    bool operator == (const CustomAllocator<T> & rhs)
    {
        return true;
    }

    bool operator != (const CustomAllocator<T> & rhs)
    {
        return false;
    }

    template <class U>
    CustomAllocator(const CustomAllocator<U> & rhs)
        :
        m_memoryManager(std::move(rhs.m_memoryManager))
    {
    }

    T * allocate(size_t n)
    {
        const size_t numBytes = n * sizeof(T);
        void * p = m_memoryManager->allocate(numBytes);

        if (!p)
        {
            throw std::bad_alloc();
        }

        std::cout << "Allocated " << numBytes << " bytes for a " << typeid(T).name() << std::endl;
        return static_cast<T *>(p);
    }

    void deallocate(T * p, size_t numObjects)
    {
        const size_t numBytes = sizeof(*p);

        m_memoryManager->free(p);
        std::cout << "Deallocated " << numBytes << " bytes for a " << typeid(T).name() << std::endl;
    }

    void construct(T * p, const T & x)
    {
        // 'Placement new' constructs an object at a specified location
        // The custom allocator seperates allocation from construction
        new(p) T(x);
    }

    void destroy(T * p)
    {
        p->~T();
    }
};
Run Code Online (Sandbox Code Playgroud)

我对此有几个问题。

  1. 我该如何做运算符==和运算符!=而不是拥有一个唯一的指针成员变量?我是否只比较内存管理器的地址?为什么该标准要求我无论如何都应该实施比较运算符,如果只能假设其中之一并且不能复制呢?还是呢?

  2. 在复制构造函数中为类型U移动内存管理器是否安全?我假设当STL容器为其他类型创建新的分配器时,它不再使用旧的分配器。那是对的吗?

  3. http://en.cppreference.com/w/cpp/concept/Allocator#Allocator_completeness_requirements上,我再也看不到构造或销毁方法了。我仍然需要实现那些方法吗?

  4. 将参数用作STL容器的参数时,如何将其传递给分配器的构造函数?


void RunCustomAllocator()
{
    // Does not compile
    std::vector<ComplexNumber, CustomAllocator<ComplexNumber> > myVector;
    ComplexNumber number(1, 1);
    myVector.push_back(number);
}
Run Code Online (Sandbox Code Playgroud)

我在这里吠叫正确的树吗?这几天我们是如何进行自定义内存管理的?