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

时间:2017-01-25 14:48:17

标签: c++ dictionary

我的问题背后的目的是使用process.env.NODE_ENV = 'test'; var chai = require('chai'); var chaiHttp = require('chai-http'); var server = require('../app'); var m_Kbase_data = require('../model/Kbase'); var m_KbaseScript_schema = require('../model/KbaseScript'); var should = chai.should(); var expect = chai.expect; chai.use(chaiHttp); describe('KBasefull', function() { m_Kbase_data.collection.drop(); it('need to add a kbase article for testing /KBase', function (done) { chai.request('http://127.0.0.1:5000') .post('/kbase') .send({Problem: "Problem", description: "Description", resolution: "Something to fix"}) .end(function(err, res){ res.should.have.status(200); done(); }); }); } (即插入,删除,访问),保证不会从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 } } 没有这样的重载。

你们有解决方案吗?

2 个答案:

答案 0 :(得分:2)

  

我的问题背后的目的是使用std :: map(即插入,   删除,访问)保证没有异常将从中抛出   std :: map implementation。

如果在实例化

时保留默认std::allocator

std :: map < Key,T,Com = std :: less < Key >,Allocator = std::allocator<...> > 的;

然后你不能做任何例外保证。在insertsemplace

  

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

在大多数STL实现中,我没有看到如何在没有内存分配的情况下进行插入,因为they mostlyRed Black Trees与堆分配的节点一起使用。您可能希望使用从现有内存池分配的自定义分配器,具有noexcept保证。或者写自己的容器。

答案 1 :(得分:1)

使用节点提取和移植:

{
    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