在std :: allocator rebind上传输对象所有权

时间:2011-05-09 18:36:04

标签: c++ standard-library allocator

我有一个Visual Studio 2008 C ++应用程序,我正在实现std::vector等容器中使用的标准分配器的替代品。但是,我遇到了一个问题。我的实现依赖于拥有资源句柄的分配器。在使用rebind功能的情况下,我需要将句柄的所有权转移到新的分配器。像这样:

template< class T >
class MyAllocator
{
public:
    template< class U >
    explicit MyAllocator( const MyAllocator< U >& other ) throw() 
        :  h_( other.Detach() ) // can't do this to a `const`
    {
    };

    // ...

private:
    HANDLE Detach()
    {
        HANDLE h = h_;
        h_ = NULL;
        return h;
    };

    HANDLE h_;
}; // class MyAllocator

不幸的是,我无法解除句柄所有权的旧分配器,因为它是const。如果我从重新绑定构造函数中删除const,则容器将不接受它。

error C2558: class 'MyAllocator<T>' : no copy constructor available or copy constructor is declared 'explicit'

这个问题有好办法吗?

谢谢,

PaulH

4 个答案:

答案 0 :(得分:2)

没有真正了解分配器(从不需要它们):你的副本ctor需要一个const引用,因此承诺不改变other对象,但无论如何你都试图改变它。虽然有些课程是按照这种方式设计的(std::auto_ptr),但这看起来很可疑 从语法上讲,您始终可以声明h_ mutable,并使Detach()成为const成员函数,但我会认真质疑这个语义设置,在使用大刀进入句法丛林之前。

答案 1 :(得分:1)

如果您将h_声明为mutable会怎样?

答案 2 :(得分:1)

您可以通过额外的间接级别来解决这个问题,但这不是一个理想的解决方案。基本上,您的分配器将有一个指针到一个句柄,该句柄将在构造函数/析构函数中分配/解除分配。它指向的句柄在整个过程中都是非const的,因此您可以将句柄从一个分配器“移动”到另一个分配器。这确实会给分配器增加一些开销。

我不知道你的确切情况,但似乎应该仔细考虑一个非平凡的可复制的有状态分配器的所有含义。是否有其他方法可以简化其设计,因此它没有只移动的句柄?

答案 3 :(得分:1)

您无法转移所有权,因为即使在单个容器中也可以多次复制和反弹分配器,并且同时使用生成的实例。

您必须共享资源。使用reference-count为资源创建间接。类似的东西:

class SharedHandle {
    HANDLE h_;
    int count;
    SharedHandle(HANDLE h) : h_(h), count(1) {}
    ~SharedHandle() { CloseHandle(h_); } // or whatever to release the resource.
    SharedHandle *Ref() { ++count; return this; }
    void Unref() { if(!--count) delete this; }
}

而不是:

explicit MyAllocator( const MyAllocator< U >& other ) throw() 
:  h_( other.h_->Ref() )

除了自然需要分配异构块(如hash_map / unordered_map的容器之外,已知容器的Microsoft实现会分配各种奇怪的东西。当我在一个Windows应用程序中跟踪分配时,从STL内部的某个地方传来了许多奇怪大小的分配。