allocate_shared附加字节缓冲区

时间:2012-12-22 14:03:21

标签: c++ boost shared-ptr

任务:shared_ptr,T =缓冲区,缓冲区有动态字节数(末尾为uint8_t []);

allocate_shared是否保证将保留此订单: [shared_ptr data] [object] [附加butebuffer]

因为其他方式不起作用,例如: [对象] [shared_ptr数据] [附加butebuffer]

其他实施想法?

template <class T>
class addon_allocator : public boost::noncopyable
{
public : 
    typedef T value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

public : 
    template<typename U> struct rebind
    {
        typedef addon_allocator<U> other;
    };

public : 
    explicit addon_allocator( std::size_t size )
        :m_size( size )
    {
    }

    ~addon_allocator()
    {
    }

    addon_allocator(const addon_allocator<T>& other)
        :m_size(other.m_size)
    {
    }

    template <class U>
    explicit addon_allocator(const addon_allocator<U>& other)
        :m_size(other.get_addon_size())
    {
    }

    pointer address(reference r)
    {
        return &r;
    }
    const_pointer address(const_reference r)
    {
        return &r;
    }

    pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer = 0)
    {
        assert( cnt == 1 );
        return reinterpret_cast<pointer>(
            ::operator new(sizeof(T) + m_size)
            );
    }
    void deallocate(pointer p, size_type)
    {
        ::operator delete(p);
    }

    std::size_t get_addon_size() const
    {
        return m_size;
    }
private:
    const std::size_t m_size;
};

class buffer : public boost::noncopyable
{
public:
    buffer( std::size_t size )
        :m_size(size)
    {
    }
    const std::size_t m_size;
    uint8_t m_data[];
    static boost::shared_ptr<buffer> create(std::size_t size)
    {
        boost::allocate_shared<buffer>(
            addon_allocator<buffer>(size),
            size
            );
    }
};

2 个答案:

答案 0 :(得分:2)

您的代码也可以在libstdc ++中使用std::allocate_shared的实现,但我认为没有任何保证内存布局会这样。

由于您已经有一个用于创建shared_ptr的特定函数,因此手动执行内存分配会更加轻松,而不是将allocate_shared与自定义分配器一起使用:

class buffer : public boost::noncopyable
{
public:
    buffer( std::size_t size ) throw()
        :m_size(size)
    {
    }
    const std::size_t m_size;
    uint8_t m_data[];
    static boost::shared_ptr<buffer> create(std::size_t size)
    {
        void* addr = ::operator new(sizeof(buffer) + size);
        return boost::shared_ptr<buffer>(::new(addr) buffer(size));
    }
};

这种方式不需要分配器类型,维护的代码更少,代码全部集中在一个地方。这确实失去了allocate_shared仅进行单个分配(并保持shared_ptr ref计算与对象相邻的元数据)的优势,但它保证可以在任何实现上工作......由此权衡取决于您是值得的。

此代码依赖于buffer构造函数为无抛出,如果它可以抛出create函数需要捕获异常,释放内存并重新抛出。

我还会考虑将构造函数设为私有,因此buffer对象只能由create函数创建。

答案 1 :(得分:0)

最后我决定使用:

    使用T = buffer
  • boost :: intrusive_ptr
  • boost :: atomic ,T = std :: size_t用于引用计数(不是boost,单独库的一部分)

便携式单一分配。