std map - 如果我知道元素不存在,那么使用什么而不是[]

时间:2014-04-20 08:55:01

标签: c++ c++11

我正在使用这样的代码:

std::unordered_map<int64_t /*id_ord*/, LimitOrder> futOrders;

LimitOrder& newOrder = futOrders[orderId];
newOrder.Operation = side;
newOrder.InstrumentId = instrumentId;
newOrder.Lots = lots;
newOrder.Price = price;
newOrder.State = Active;
newOrder.Id = orderId;

我知道futOrders不包含orderId,因此[]以这种方式工作:函数使用该键插入一个新元素并返回对它的引用映射值。

理想情况下我想要这种行为:&#34;只需添加到集合中,否则以某种方式表明该元素已经存在。异常是优先考虑的。&#34;我希望这能在代码中清楚地表明它假设元素是新的,并且可能是为了获得更好的性能。你能推荐一些东西,或者我拥有的东西是最好的吗?

7 个答案:

答案 0 :(得分:2)

您可以使用emplace

std::unordered_map<int64_t /*id_ord*/, LimitOrder> futOrders;

auto i = futOrders.emplace(
           std::piecewise_construct, std::tie(orderId), std::make_tuple());
if (i.second) {
    auto &newOrder = i.first->second;
    //newOrder is a newly inserted order
}
else {
    //order already present at orderId...
}

这可以包含在辅助函数

template<typename Map, typename ...Args>
typename Map::mapped_type &emplace_new_element(Map &&map, Args &&...args) {
    auto i = std::forward<Map>(map).emplace(std::forward<Args>(args)...);
    assert(i.second); 
    return i.first->second;
}

用法:

auto &newOrder = emplace_new_element(
    futOrders,
    std::piecewise_construct, std::tie(orderId), std::make_tuple());

答案 1 :(得分:1)

如果元素存在则抛出:

if (fitOrders.count(orderID))
{
  // throw your preferred exception
} 

// insert the order
LimitOrder& newOrder = futOrders[orderId];
....

答案 2 :(得分:1)

map::insert返回一个包含迭代器的对,该迭代器具有给定的键和一个布尔值,表示是否插入了新元素。

std::unordered_map<int64_t /*id_ord*/, LimitOrder> futOrders;

LimitOrder newOrder;

// Initialize newOrder..

bool inserted = futOrders.insert( make_pair( orderId, newOrder) ).second;

if (!inserted) 
{
    // Element was not inserted because there is already another one with the same key
    // Throw an exception here or do whatever you like
}

如果初始化LimitOrder的成本可以忽略不计,那么这种方法很有效。否则,您应使用find检查具有给定密钥的元素是否已存在,如果insert返回find,则使用map::end()

答案 3 :(得分:1)

您应该使用std::unordered_map::insert

std::pair<iterator,bool> insert( const value_type& value );
  

返回一个由插入元素的迭代器组成的对(或   阻止插入的元素和 bool表示   插入是否发生

答案 4 :(得分:0)

与我之前的建议相似:

LimitOrder& newOrder = futOrders[orderId];
if (!newOrder.empty())
{
    // do stuff that says order is not empty as you expect. 
}
else
{
    // fill in order. 
}

答案 5 :(得分:0)

这些都没有抛出异常,但insert和emplace(C ++ 11)都返回一对迭代器和一个bool,告诉你它是否已经存在。

答案 6 :(得分:0)

如果您不关心插入的内容或插入内容,请使用

之类的内容
if(futOrders.count(orderId)>0) {
     // exists, signal it as you desire
} else {
     .... // your insertion code
}

如果您有兴趣返回它所在的内容或插入的内容,那么使用findinsert两者都会得到一个只有索引一次的迭代器