簡體   English   中英

有沒有理由在C ++ 1z中使用std :: map :: emplace()而不是try_emplace()?

[英]Is there any reason to use std::map::emplace() instead of try_emplace() in C++1z?

在C ++ 17中, std::mapstd::unordered_map獲得了一個新的成員函數模板: try_emplace() n4279中提出的這個新增加的行為與emplace emplace()類似,但具有以下優點:

  • 如果插入沒有發生, try_emplace()不會從rvalue參數移動。 這在處理值為僅移動類型的映射時非常有用,例如std::unique_ptr
  • try_emplace()把密鑰和參數給mapped_type分開,這使得它稍微大於在來表示通用存取器更加直觀value_type (這是std::pair )。

鑒於上述優點,你會永遠使用emplace()從C ++ 11的替代try_emplace()編寫C ++ 1Z-唯一代碼時,從C ++ 1Z?

try_emplace確實可以代替大多數使用emplace ,但如果你有一個不尋常的用例map用不可復制和不可移動的密鑰類型, try_emplace不會工作,因為它復制或移動的關鍵。 在這種情況下,你必須使用emplacestd::pair分段施工構造 ,以避免拷貝和移動。

即使您的密鑰類型是可復制和/或可移動的,分段構造是避免復制或移動構造密鑰的唯一方法,因此可能存在您更喜歡使用try_emplace

try_emplace也不支持異構查找 - 它不能,因為它需要密鑰。

假設我們有一個std::map<std::string, int, std::less<>> counts; 和一個std::string_view sv 我想做相當於++counts[std::string(sv)]; ,但我不想創建一個臨時的std::string ,這只是浪費,特別是如果字符串已經存在於地圖中。 try_emplace無法幫助你。 相反,你會做類似的事情

if(auto lb = counts.lower_bound(sv); lb != counts.end() && lb->first == sv) {
    ++lb->second;
}
else {
    counts.emplace_hint(lb, sv, 1);
}

我總是喜歡try_emplace over emplace。 一個關鍵的區別是,如果密鑰已經存在,try_emplace將不會構造與密鑰關聯的對象。這將提高性能,以防該類型的對象創建成本高昂

例如下面的代碼(來自https://github.com/PacktPublishing/Cpp17-STL-Cookbook/blob/master/Chapter02/efficient_insert_or_reassign_to_map.cpp的示例)

#include <iostream>
#include <functional>
#include <list>
#include <map>

using namespace std;

struct billionaire {
    string name;
    double dollars;
    string country;
};

int main()
{
    list<billionaire> billionaires {
        {"Bill Gates", 86.0, "USA"},
        {"Warren Buffet", 75.6, "USA"},
        {"Jeff Bezos", 72.8, "USA"},
        {"Amancio Ortega", 71.3, "Spain"},
        {"Mark Zuckerberg", 56.0, "USA"},
        {"Carlos Slim", 54.5, "Mexico"},
        // ...
        {"Bernard Arnault", 41.5, "France"},
        // ...
        {"Liliane Bettencourt", 39.5, "France"},
        // ...
        {"Wang Jianlin", 31.3, "China"},
        {"Li Ka-shing", 31.2, "Hong Kong"}
        // ...
    };

    map<string, pair<const billionaire, size_t>> m;

    for (const auto &b : billionaires) {
        auto [iterator, success] = m.try_emplace(b.country, b, 1);

        if (!success) {
            iterator->second.second += 1;
        }
    }


    for (const auto & [key, value] : m) {
        const auto &[b, count] = value;

        cout << b.country << " : " << count << " billionaires. Richest is "
        << b.name << " with " << b.dollars << " B$\n";
    }
}

對於上面的代碼

m.try_emplace(b.country, b, 1);

如果插入不成功,則不會構造對,這會增加性能

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM