C++ STL:为什么分配器不会增加容器的内存占用?

Leo*_*ruz 3 c++ stl allocator

下面的代码片段(参见 Godbolt)表明大分配器不会增加 STL 容器的内存占用,但大比较器会。为什么会这样?

// compiled with x86-64 gcc 10.3, -std=c++17
#include <functional>
#include <iostream>
#include <memory>
#include <set>

struct MyLess : public std::less<int>
{
    char dummy[1024];
};

struct MyAllocator : public std::allocator<int>
{
    char dummy[1024];
};

int main()
{
    std::cout << sizeof(std::set<int, MyLess>) << std::endl;  // prints 1064
    std::cout << sizeof(std::set<int, std::less<int>, MyAllocator>) << std::endl;  // prints 48
    return 0;
}

Run Code Online (Sandbox Code Playgroud)

Hol*_*Cat 7

您的分配器未被使用。

默认情况下,std::set接收std::allocator<int>,但它需要分配某种节点,而不是ints。它std::allocator_traits::rebind用于为其内部节点类型获取不同的分配器。

Pre-C++20std::allocator有一个rebind成员类型,您可以继承并std::allocator_traits::rebind找到它。这rebind指向std::allocator,所以这就是你得到的。

从 C++20 开始,没有rebindin std::allocator,因此std::allocator_traits::rebind直接修改分配器的第一个模板参数,并且由于它不是模板,因此会出现编译错误。

一个可能的解决方案是让你的分配器成为一个模板,并提供你自己的rebind(可能是格式错误的,然后模板参数将被自动替换):

template <typename T>
struct MyAllocator : public std::allocator<T>
{
    char dummy[1024];
    struct rebind {}; // Malformed `rebind` to hide the inherited one, if any.
};
Run Code Online (Sandbox Code Playgroud)

然后1072打印给我。