在c++中使用自定义分配器,将容器分配给迭代器时,会出现什么问题?

问题描述 投票:0回答:1

我在编译以下代码时遇到 GCC 抱怨类型不匹配的问题:

#include <iostream>
#include <cstdint>
#include <vector>
#include <limits>

template <class T>
struct Mallocator {
    typedef T value_type;

    Mallocator() = default;

    template <class U>
    Mallocator(const Mallocator<U>&) {}

    T* allocate(std::size_t n) {
        if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
            throw "std::bad_array_new_length";

        if (auto p = static_cast<T*>(malloc(n * sizeof(T)))) {
            report(p, n);
            return p;
        }

        throw std::bad_alloc();
    }

    void deallocate(T* p, std::size_t n) {
        report(p, n, 0);
        free(p);
    }

   private:
    void report(T* p, std::size_t n, bool alloc = true) const {
        std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n
                  << " bytes at " << std::hex << std::showbase
                  << reinterpret_cast<void*>(p) << std::dec << '\n';
    }
};

struct Foo
{
    Foo(int f): m_values{f} {}
    std::vector<int, Mallocator<int> > m_values;
    std::vector<int>::iterator begin() { return m_values.begin(); }
};

int main() {
    Foo f(1);
    return 0;
}

MSVC 和 Clang(启用 libc++)可以很好地编译相同的代码。当迭代器跳转到下一个值时,没有问题吗?如果分配器分配的大小与标准分配器不同,它如何知道内存中下一个要迭代的值在哪里?

c++ gcc iterator allocator
1个回答
0
投票

std::vector<int>
是一种类型,
std::vector<int, Mallocator<int> >
是另一种类型。未指定
std::vector<int, Mallocator<int> >::iterator
是否可转换为
std::vector<int>::iterator

它们可能不兼容的一个简单方法是它们是在

vector
中定义的,因此它们本身是不相关的类型。

它们兼容的一个简单方法是它们在

vector
外部定义并在其中使用别名,并且仅依赖于元素类型参数。

非常简单的修复方法是

Foo
在其声明中使用正确的类型。

struct Foo
{
    Foo(int f): m_values{f} {}
    std::vector<int, Mallocator<int> > m_values;
    std::vector<int, Mallocator<int> >::iterator begin() { return m_values.begin(); }
};
© www.soinside.com 2019 - 2024. All rights reserved.