使用自定义分配器的std::string

3

我目前正在编写一个内存调试器,为此我需要让stl容器对象使用未跟踪的分配器。

我的整个代码库中都有std::string,因此我使用了typedef将其设置为使用我的未跟踪的分配器:

typedef std::basic_string<char, std::char_traits<char>, UntrackedAllocator<char>> String;

现在我尝试做这个操作:
String str { "Some string" };
String copy = str;

我收到了这个错误信息:

/usr/local/include/c++/7.1.0/ext/alloc_traits.h:95:67: error: no matching function for call to 'UntrackedAllocator<char>::UntrackedAllocator(UntrackedAllocator<char>)' { return _Base_type::select_on_container_copy_construction(__a); }

这是我的非跟踪分配器的样子:
#pragma once

#define NOMINMAX
#undef max

template <typename T>
class UntrackedAllocator {
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 UntrackedAllocator<U> other;
    };

public:
    inline explicit UntrackedAllocator() {}
    inline ~UntrackedAllocator() {}
    inline explicit UntrackedAllocator(UntrackedAllocator const&) {}
    template<typename U>
    inline explicit UntrackedAllocator(UntrackedAllocator<U> const&) {}

    //    address
    inline pointer address(reference r) {
        return &r;
    }

    inline const_pointer address(const_reference r) {
        return &r;
    }

    //    memory allocation
    inline pointer allocate(size_type cnt,
        typename std::allocator<void>::const_pointer = 0) {
        T *ptr = (T*)malloc(cnt * sizeof(T));
        return ptr;
    }

    inline void deallocate(pointer p, size_type cnt) {
        free(p);
    }

    //   size
    inline size_type max_size() const {
        return std::numeric_limits<size_type>::max() / sizeof(T);
    }

    // construction/destruction
    inline void construct(pointer p, const T& t) {
        new(p) T(t);
    }

    inline void destroy(pointer p) {
        p->~T();
    }

    inline bool operator==(UntrackedAllocator const& a) { return this == &a; }
    inline bool operator!=(UntrackedAllocator const& a) { return !operator==(a); }
};

这是我第一次使用自定义分配器,所以我不知道它的运作方式。如果其中一个字符串使用自定义分配器,则不能执行str1 = str2,这非常麻烦。


2
你的关系运算符有误。分配器应该在一个可以释放另一个分配的情况下进行相等比较。 - Kerrek SB
http://stackoverflow.com/help/mcve - Benjamin Lindley
2
错误信息意味着你在某个地方使用了复制构造函数。你发布的代码没有使用复制构造函数,除非你的下标运算符返回值。无论如何,使复制构造函数显式很少有用。从复制构造函数中删除“explicit”,问题应该就解决了。 - Dietmar Kühl
@KerrekSB 你是什么意思? - Taylor Bishop
1个回答

3
问题在于将复制构造函数声明为explicit。将UntrackedAllocator的复制构造函数更改为:
inline UntrackedAllocator(UntrackedAllocator const&) {}

解决编译问题后,一切都正常运作:
int main() {
  String str { "13" };
  String copy = str;
  const char* cstr = str.c_str();
  int out = atoi(cstr);
}

这是因为std::basic_string的赋值运算符需要对分配器进行隐式拷贝构造,其接受的参数为const std::basic_string&

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接