如何使类通过作用域分配器?

时间:2016-07-18 16:38:17

标签: c++ memory-management allocator

我正在尝试创建一个可以在带有自定义分配器的向量中使用的分配器识别类。该类有一个std :: string作为成员,我希望这个字符串像分配类一样分配给分配器。

如何使这样的分配器识别类?下面的示例在竞技场上分配类ClassA,但它在默认的分配器上分配ClassA:mVarC。

using XAlloc1 = Allocator<char>;
using xstring = basic_string< char, char_traits<char>, XAlloc1 >;

template< typename Alloc = std::allocator<xstring> >
class ClassA : public Alloc {
public:
    ClassA( xstring & str, Alloc & alloc )
        : mVarA( int() ), mVarB( double() ), mVarC( str, alloc ) {
    }

    ClassA( xstring & str )
        : mVarA( int() ), mVarB( double() ), mVarC( str ) {
    }

    int mVarA;
    double mVarB;
    xstring mVarC;
};

using XAlloc2 = scoped_allocator_adaptor< Allocator<xstring>,
                                          Allocator<char> >;
using XClassA = ClassA< XAlloc2 >;

using XAlloc3 = scoped_allocator_adaptor< Allocator<XClassA>,
                                          Allocator<xstring>,
                                          Allocator<char> >;
using xvec = vector< XClassA, XAlloc3 > ;

void foo() {
    MemoryPool<145> arena();
    XAlloc3 alloc( arena );
    xvec v( alloc );
    v.emplace_back( XClassA( xstring( "Another very long text" ) ) );
}

1 个答案:

答案 0 :(得分:0)

为了使课程“分配器能够识别”#39;你必须

  • 使用allocator_type = Alloc包含&#39;&#39;这样分配器就可以查询它。
  • 编写

    的分配器版本
    • 普通构造函数。 ClassA(const xstring&amp; str,const Alloc&amp; alloc)
    • 复制构造函数。 ClassA(const ClassA&amp; o,const Alloc&amp; alloc)
    • 移动构造函数。 ClassA(ClassA&amp;&amp; o,const Alloc&amp; alloc)

    构造函数必须具有&#39; const Alloc&amp;&#39;参数作为尾随参数, 除非您指定该类使用前导分配器参数。

    • 普通构造函数。 ClassA(allocator_arg_t,const Alloc&amp; alloc,const xstring&amp; str)
    • 复制构造函数。 ClassA(allocator_arg_t,const Alloc&amp; alloc,const ClassA&amp; o)
    • 移动构造函数。 ClassA(allocator_arg_t,const Alloc&amp; alloc,ClassA&amp;&amp; o)

    未使用allocator_arg_t。它是一个空结构。 (我不知道为什么它必须在那里。它必须。

template< typename Alloc = std::allocator<xstring> >
class ClassA {
public:
    using allocator_type = Alloc;

    ClassA( const xstring & str, const Alloc & alloc ) 
        : mVarA( int() ), mVarB( double() ), mVarC( str, alloc ) { }
    ClassA( const xstring & str ) 
        : mVarA( int() ), mVarB( double() ), mVarC( str ) { }
    ClassA( const ClassA & o, const Alloc & alloc ) 
        : mVarA( o.mVarA ), mVarB( o.mVarB ), mVarC( o.mVarC, alloc ) { }
    ClassA( const ClassA & o ) 
        : VarA( o.mVarA ), mVarB( o.mVarB ), mVarC( o.mVarC ) { }
    ClassA( ClassA && o, const Alloc & alloc ) 
        : mVarA( move( o.mVarA ) ), mVarB( move( o.mVarB ) ), mVarC( move( o.mVarC ), alloc ) { }
    ClassA( ClassA && o ) 
        : mVarA( move( o.mVarA ) ), mVarB( move( o.mVarB ) ), mVarC( move( o.mVarC ) ) { }

    int mVarA;
    double mVarB;
    xstring mVarC;
};

// // You can specify an allocator for each of the nested containers.
//using XAlloc2 = scoped_allocator_adaptor< Allocator<xstring>,
//                                          Allocator<char> >;
//using XClassA = ClassA< XAlloc2 >;
//
//using XAlloc3 = scoped_allocator_adaptor< Allocator<XClassA>,
//                                          Allocator<xstring>,
//                                          Allocator<char> >;
//using xvec = vector< XClassA, XAlloc3 > ;

// Or you can just specify one allocator. This allocator will then be reused for all nested containers.
using XAlloc2 = scoped_allocator_adaptor< Allocator<xstring> >;
using XClassA = ClassA< XAlloc2 >;
using xvec = vector< XClassA, XAlloc2 >;

void funk() {
    MemoryPool<145> arena();
    XAlloc2 alloc( arena );
    xvec v( alloc );
    v.push_back( XClassA( xstring( "Another very long text" ) ) );
}