gpt4 book ai didi

c++ - 在 C++ map 中插入 vs emplace vs operator[]

转载 作者:IT老高 更新时间:2023-10-28 11:30:07 30 4
gpt4 key购买 nike

我第一次使用 map ,我意识到有很多方法可以插入元素。您可以使用 emplace() , operator[]insert() , 加上变体,如使用 value_typemake_pair .虽然有很多关于所有这些的信息和关于特定案例的问题,但我仍然无法理解大局。
所以,我的两个问题是:

  • 他们每个人相对于其他人的优势是什么?
  • 是否需要在标准中添加 emplace?没有它,以前有什么是不可能的吗?
  • 最佳答案

    在 map 的特殊情况下,旧的选项只有两个:operator[]insert (insert 的不同口味)。所以我将开始解释这些。
    operator[]是一个查找或添加运算符。它将尝试在 map 中找到具有给定键的元素,如果它存在,它将返回对存储值的引用。如果没有,它将创建一个新元素插入到位并使用默认初始化并返回对它的引用。
    insert函数(在单一元素风格中)需要一个 value_type ( std::pair<const Key,Value> ),它使用 key ( first 成员)并尝试插入它。因为 std::map如果存在现有元素,则不允许重复,它不会插入任何内容。

    两者的第一个区别是operator[]需要能够构造一个默认的初始化值,因此对于不能默认初始化的值类型是不可用的。两者之间的第二个区别是当已经存在具有给定键的元素时会发生什么。 insert函数不会修改 map 的状态,而是返回一个迭代器到元素(和一个 false 表示它没有插入)。

    // assume m is std::map<int,int> already has an element with key 5 and value 0
    m[5] = 10; // postcondition: m[5] == 10
    m.insert(std::make_pair(5,15)); // m[5] is still 10

    insert的情况下参数是 value_type 的对象,可以用不同的方式创建。您可以使用适当的类型直接构造它或传递来自 value_type 的任何对象。可以构造,这是 std::make_pair的地方开始发挥作用,因为它允许简单地创建 std::pair对象,虽然它可能不是你想要的......

    以下调用的净效果类似:
    K t; V u;
    std::map<K,V> m; // std::map<K,V>::value_type is std::pair<const K,V>

    m.insert( std::pair<const K,V>(t,u) ); // 1
    m.insert( std::map<K,V>::value_type(t,u) ); // 2
    m.insert( std::make_pair(t,u) ); // 3

    但实际上并不相同...... [1] 和 [2] 实际上是等价的。在这两种情况下,代码都会创建一个相同类型的临时对象( std::pair<const K,V> )并将其传递给 insert功能。 insert函数将在二叉搜索树中创建适当的节点,然后复制 value_type部分从参数到节点。使用优势 value_type是吗,嗯, value_type始终匹配 value_type ,您不能错误输入 std::pair 的类型争论!

    区别在于[3]。函数 std::make_pair是一个模板函数,它将创建一个 std::pair .签名是:
    template <typename T, typename U>
    std::pair<T,U> make_pair(T const & t, U const & u );

    我故意不向 std::make_pair 提供模板参数,因为这是常见的用法。这意味着模板参数是从调用中推导出来的,在本例中为 T==K,U==V ,所以拨打 std::make_pair将返回 std::pair<K,V> (注意丢失的 const )。签名需要 value_type接近但与调用 std::make_pair 的返回值不同.因为它足够接近,它会创建一个正确类型的临时文件并复制初始化它。这将依次复制到节点,共创建两个拷贝。

    这可以通过提供模板参数来解决:
    m.insert( std::make_pair<const K,V>(t,u) );  // 4

    但这仍然容易出错,就像在 case [1] 中显式键入类型一样。

    到目前为止,我们有不同的调用方式 insert需要创建 value_type在外部并将该对象的拷贝复制到容器中。或者,您可以使用 operator[]如果该类型是默认可构造和可分配的(有意仅关注 m[k]=v ),并且它需要一个对象的默认初始化并将值复制到该对象中。

    在 C++11 中,通过可变模板和完美转发,提供了一种通过 emplaceing(就地创建)将元素添加到容器中的新方法。 emplace不同容器中的函数基本上做相同的事情:函数不是获取要复制到容器中的源,而是获取将被转发到存储在容器中的对象的构造函数的参数。
    m.emplace(t,u);               // 5

    在[5]中, std::pair<const K, V>未创建并传递给 emplace ,而是对 t 的引用和 u对象被传递给 emplace将它们转发给 value_type 的构造函数数据结构内的子对象。在这种情况下,没有 std::pair<const K,V> 的拷贝完全做到了,这是 emplace的优势在 C++03 替代品。如 insert 的情况它不会覆盖 map 中的值。

    一个我没有想过的有趣问题是如何 emplace实际上可以为 map 实现,这在一般情况下不是一个简单的问题。

    关于c++ - 在 C++ map 中插入 vs emplace vs operator[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17172080/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com