【问题标题】:C++ STL: Why allocators don't increase memory footprint of containers?C++ STL:为什么分配器不会增加容器的内存占用?
【发布时间】:2021-10-06 00:54:15
【问题描述】:

以下代码 sn-p(see on 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;
}

【问题讨论】:

    标签: c++ stl allocator


    【解决方案1】:

    你的分配器没有被使用。

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

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

    从 C++20 开始,std::allocator 中没有 rebind,所以 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.
    };
    

    然后为我打印1072

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 2020-08-10
      • 2016-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2011-12-02
      • 1970-01-01
      相关资源
      最近更新 更多