如何在 std::map 中添加元素自己进行分配

How to add element in std::map doing allocation oneself?

本文关键字:自己 元素 分配 添加 std map      更新时间:2023-10-16

我问题背后的目的是使用std::map(即插入,删除,访问),并保证std::map实现不会引发异常。

删除不是问题,如果仔细使用东西(例如,没有检查就没有at),则访问也不是问题。

但插入是另一个问题。在此代码中:

#include <map>
struct foo{};
int main()
{
  std::map<int, foo> my_map;
  my_map.insert(std::pair<int, foo>(42, foo{}));
}

my_map做一些分配,如果没有更多的内存,就抛出。

现在,我想要的是一种执行此操作的方法:

#include <map>
struct foo{};
int main()
{
  std::map<int, foo> my_map;
  auto my_new_pair{ new std::pair<int, foo>(42, foo{}) };
  if (my_new_pair) // ok, we could build the node
  {
    my_map.insert(my_new_pair); // no allocation, my_map only takes the "ownership" of my_new_pair
  }
}

但是没有这种超载的insert.

你们有解决方案吗?

我问题背后的目的是使用 std::map(即插入, 删除,访问),并保证不会引发异常 标准::地图实现。

std::allocator如果在实例化

std::map < 键, T, Com=std::less <> , 分配器= std::allocator<...> > ;

那么您不能做出任何例外保证。 在insertsemplace.

23.2.1/8: 除非另有说明,否则本条款中定义的所有容器 使用分配器获取内存


我不明白在大多数 STL 实现中如何在没有内存分配的情况下进行插入,因为它们主要使用带有堆分配节点的红黑树。您可能希望使用从现有内存池分配的自定义分配器,并且没有例外保证。或者编写自己的容器。

使用节点提取和转题:

{
    std::map<int, foo> staging_map;
    staging_map.emplace(42, foo{});
    real_map.insert(staging_map.extract(42));  // cannot throw
}

不是"自己"做分配,但你基本上可以用这种方法获得一个预先分配的映射节点,你可以用它来达到你自己的目的,直到你准备好将其插入到映射中,例如:

auto nh = staging_map.extract(42);
// Done initializing.
// use nh freely
real_map.insert(std::move(nh));  // guaranteed to work