1

任务:shared_ptr,T=buffer,其中buffer有动态字节数(uint8_t[]结尾);

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

因为其他方式不起作用,例如:[object][shared_ptr data][additional 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
            );
    }
};
4

2 回答 2

2

您的代码也将与std::allocate_sharedlibstdc++ 中的实现一起使用,但我认为不能保证内存布局会这样。

由于您已经有一个用于创建的特定函数,因此手动进行内存分配而不是使用自定义分配器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函数创建。

于 2012-12-29T15:20:28.197 回答
0

最后我决定使用:

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

便携单分配。

于 2013-01-01T23:41:14.277 回答