C++ 中的“使用分配器”和“作用域分配器”构造是什么

2024-04-21

有相当多的few https://stackoverflow.com/search?q=uses_allocator 问题 https://stackoverflow.com/search?q=scoped_allocator在这里谈论使用分配器 https://en.cppreference.com/w/cpp/memory/uses_allocator#Uses-allocator_construction and 作用域分配器 https://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor但它们来自于知道它们是什么以及它们的用途的假设。

通常的 C++ 参考文献中的解释解释了“内容”,但没有解释如何或为什么。

该网站缺少一个规范的答案,该答案将为那些不熟悉该主题的人提供背景知识。


它是一个允许泛型容器类型(广义上的)检测泛型类型参数何时期望与分配器一起使用的协议。

然后,他们可以决定通过自动将外部分配器传播到内部类型来支持这一点。典型的例子是当你想要一个std::map<std::vector<std::string>, std::set<int> >全部使用相同的分配器系列。

包含嵌套的类型allocator_typetypename 将自动被检测为uses_allocator类型,包括所有标准容器。

典型其他uses_allocator标准库中的类型有std::pair and std::tuple,还有函数包装类型(std::function, std::packaged_type)和容器适配器(std::stack和朋友)。

作用域分配器允许调整外部分配器或外部分配器和一组内部分配器(如果它们不相同),从而通知作用域分配器感知容器要用于内部“使用分配器”类型的分配器类型。

来自 boost 文档scoped_allocator_adaptor:

该类是 C++03 兼容的实现std::scoped_allocator_adaptor。 类模板scoped_allocator_adaptor是一个分配器模板,指定 容器(与任何其他容器一样)使用的内存资源(外部分配器) allocator 执行)并且还指定要传递给的内部分配器资源 容器内每个元素的构造函数。

该适配器使用一个外部分配器和零个或多个内部分配器进行实例化 类型。如果仅使用一种分配器类型实例化,则内部分配器 成为scoped_allocator_adaptor本身,因此使用相同的分配器 容器和容器内每个元素的资源,如果 元素本身是容器,它们的每个元素都是递归的。

如果使用多个分配器实例化,则第一个分配器是 外部分配器供容器使用,第二个分配器被传递给 容器元素的构造函数,以及元素本身 是容器,第三个分配器被传递给元素的元素,并且 很快。如果容器嵌套的深度大于容器的数量 分配器,最后一个分配器被重复使用,就像在单一分配器中一样 对于任何剩余的递归。

根据我的经验,Boost Container 始终比大多数标准库实现更好地支持该协议,但我承认我已经很多年没有检查过这些协议的状态了。

我刚刚为您提供了一个使用示例scoped_allocator_adaptor在这个答案中:boost进程间是否支持在进程之间共享包含指针的对象? https://stackoverflow.com/questions/72310393/does-boost-interprocess-support-sharing-objects-containing-pointers-between-proc/72312694#72312694。在那张照片里,Shared::Bar是内部“uses-allocator”类型的一个示例,它通知容器(vector)在构造元素时传递其分配器的(转换后的)副本。

我在此处复制该答案的代码列表,以确保示例参考不会过时:

住在科里鲁 http://coliru.stacked-crooked.com/a/3dece79f14055b92

#include <boost/container/scoped_allocator.hpp>
#include <boost/container/string.hpp>
#include <boost/container/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <string>
namespace bip = boost::interprocess;

namespace Shared {
#ifdef COLIRU
    using Segment = bip::managed_mapped_file;
#else
    using Segment = bip::managed_shared_memory;
#endif
    using Mgr     = Segment::segment_manager;

    template <typename T>
    using Alloc = boost::container::scoped_allocator_adaptor< //
        bip::allocator<T, Mgr>>;

    template <typename T> using Vector = std::vector<T, Alloc<T>>;

    using String = boost::container::basic_string< //
        char, std::char_traits<char>, Alloc<char>>;

    struct Bar {
        using allocator_type = Alloc<char>;
        String first_name, last_name;

        template <typename Alloc>
        Bar(std::allocator_arg_t, Alloc alloc) : first_name(alloc)
                                               , last_name(alloc) {}

        template <typename Alloc>
        Bar(Alloc&& alloc) : first_name(alloc)
                           , last_name(alloc) {}

        Bar(Bar const&) = default;
        template <typename Alloc>
        Bar(Bar const& rhs, Alloc alloc) : first_name(rhs.first_name, alloc), last_name(rhs.last_name, alloc) {}

        Bar& operator=(Bar const&) = default;

        template <typename Alloc> Bar(std::string_view first_name, std::string_view last_name, Alloc alloc) : 
            first_name(first_name, alloc), last_name(last_name, alloc) {}
    };

    struct Snafu {
        std::array<int, 5> no_problem;
    };

    struct Foo {
        Vector<Bar>   bars;
        Vector<Snafu> snafus;

        template <typename Alloc> //
        Foo(Alloc alloc) : bars(alloc)
                         , snafus(alloc) {}
    };
}

#include <iostream>
static inline std::ostream& operator<<(std::ostream& os, Shared::Foo const& foo) {
    os << "Foo\n================\nBars:\n";
    for (auto& [f, l] : foo.bars)
        os << " - " << f << ", " << l << "\n";

    os << "Snafus:";
    for (auto& s : foo.snafus) {
        os << "\n - ";
        for (auto el : s.no_problem)
            os << " " << el;
    }
    return os << "\n";
}


int main() { Shared::Segment msm(bip::open_or_create, "my_shared_mem", 10ull << 10);
    Shared::Foo& foo = *msm.find_or_construct<Shared::Foo>("the_foo") //
                        (msm.get_segment_manager()); // constructor arguments

    foo.bars.emplace_back("John", "Doe");
    foo.bars.emplace_back("Jane", "Deer");
    foo.bars.emplace_back("Igor", "Stravinsky");
    foo.bars.emplace_back("Rimsky", "Korsakov");

    foo.snafus.push_back({1, 2, 3});
    foo.snafus.push_back({2, 3, 4});
    foo.snafus.push_back({3, 4, 5, 6, 7});

    std::cout << foo << "\n";
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中的“使用分配器”和“作用域分配器”构造是什么 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐