简体   繁体   English

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

[英]C++ STL: Why allocators don't increase memory footprint of containers?

The following code snippet( see on godbolt ) shows that big allocators won't increase the memory footprint of STL containers, but big comparators will.下面的代码片段(参见 Godbolt )表明大分配器不会增加 STL 容器的内存占用,但大比较器会。 Why is it the case?为什么会这样?

// 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;
}

Your allocator is not being used.您的分配器未被使用。

By default, std::set receives std::allocator<int> , but it needs to allocate some kind of nodes, not int s.默认情况下, std::set接收std::allocator<int> ,但它需要分配某种节点,而不是int s。 It usesstd::allocator_traits::rebind to get a different allocator for its internal node type.它使用std::allocator_traits::rebind为其内部节点类型获取不同的分配器。

Pre-C++20 std::allocator has a rebind member type, which you inherit, and which std::allocator_traits::rebind finds. Pre-C++20 std::allocator有一个rebind成员类型,你继承它,并且std::allocator_traits::rebind找到。 That rebind points to std::allocator , so that's what you get. rebind指向std::allocator ,这就是你得到的。

Starting from C++20, there's no rebind in std::allocator , so std::allocator_traits::rebind falls back to directly modifying the first template parameter of your allocator, and since it's not a template, you get a compilation error.从 C++20 开始, std::allocator没有rebind ,因此std::allocator_traits::rebind退回到直接修改分配器的第一个模板参数,并且由于它不是模板,因此会出现编译错误。

A possible solution is to make your allocator a template, and to provide your own rebind (which can be malformed, then the template parameter will be replaced automatically):一个可能的解决方案是让你的分配器成为一个模板,并提供你自己的rebind (这可能是格式错误的,然后模板参数将被自动替换):

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

Then 1072 is printed for me.然后为我打印1072

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM