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

新手上路,请多包涵

在 C++17 中, std::mapstd::unordered_map 得到了一个新的成员函数模板: try_emplace() 。这个在 n4279 中提出的新增功能与 emplace() 类似,但具有以下优点:

  • try_emplace() 如果插入没有发生,则不会从右值参数移动。这在操作其值为仅移动类型的地图时很有用,例如 std::unique_ptr
  • try_emplace() 处理 --- 的键和参数,这使得它比用 value_type 表示的通用 mapped_type 体更直观(即 std::pair )。

鉴于上述优势,在编写仅 C++1z 的代码时,您会使用 C++11 中的 try_emplace() emplace() 不是 C++1z 中的 — 吗?

原文由 s3rvac 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 901
2 个回答

try_emplace 确实可以替换大多数用途 emplace ,但是如果您有一个 map 的不寻常用例,具有不可复制和不可移动的密钥类型, try_emplace 不起作用,因为它复制或移动密钥。在这种情况下,您必须使用 emplacestd::pair分段构造构造函数 以避免复制和移动。

即使您的密钥类型是可复制和/或可移动的,分段构造也是避免复制或移动构造密钥的唯一方法,因此在某些情况下,您可能更喜欢 try_emplace

原文由 Praetorian 发布,翻译遵循 CC BY-SA 3.0 许可协议

我总是更喜欢 try_emplace 而不是 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);

如果插入不成功,则不会构造对,这会增加性能

原文由 Hariom Singh 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题