📜  C ++ 17的地图和无序地图中的std :: try_emplace()(1)

📅  最后修改于: 2023-12-03 15:29:42.086000             🧑  作者: Mango

C++17的std::try_emplace()在地图和无序地图中的应用介绍

在C++17中,我们引入了一个新的std::try_emplace()方法,可在std::mapstd::unordered_map中使用。它是一种以更简便、更容易读取的方式来emplace值的方法。

std::try_emplace()的使用方式

std::try_emplace()方法类似于emplace()方法,区别在于后者会将元素emplace到map中,而前者则是尝试向map中emplace一个元素,前提是该元素当前不存在于map中。

下面是std::try_emplace()的函数签名:

template< class Key, class Mapped, class... Args >
std::pair<iterator, bool> try_emplace( const key_type& key, Args&&... args );

try_emplace()接受一个键值参数key和可选的args,它们将会被用来构造map中的新值。如果map中不存在对应的键,那么这些参数会被用来创建一个新的键值对。如果已经存在对应的键,那么该函数就会直接返回一个指向该键值对的迭代器。

std::try_emplace()的返回值是一个std::pair容器,其中pair::first成员表示一个指向新插入元素的迭代器,或者是已经存在元素的迭代器。pair::second成员表示一个布尔值,如果新键值对被成功emplace到map中,那么该值设置为true

std::try_emplace()std::map中的使用示例

下面是std::try_emplace()方法在std::map中的使用示例:

#include <map>
#include <iostream>
 
int main()
{
    std::map<char, std::string> my_map;
 
    // 以 pair 的形式插入元素到map中
    my_map.insert(std::pair<char, std::string>('a', "old_value"));
 
    // 尝试 emplace 新元素(因为之前已经有了 'a' 键)
    auto [iterator, success] = my_map.try_emplace('a', "new_value");
 
    if (success) {
        std::cout << "Insertion successful\n";
    } else {
        std::cout << "Insertion failed\n";
    }
 
    // 输出键值对
    for (const auto& element : my_map) {
        std::cout << element.first << " :: " << element.second << "\n";
    }
}

输出结果为:

Insertion failed
a :: old_value

我们先将一个键值对('a', "old_value")插入到map中。接着我们使用std::try_emplace()方法尝试再插入一个键值对('a', "new_value")。因为之前已经有了'a'键,所以尝试插入没有成功。最后,我们输出map中的所有键值对,可以看到,map中仍然仅有一个键值对('a', "old_value")

std::try_emplace()std::unordered_map中的使用示例

下面是std::try_emplace()方法在std::unordered_map中的使用示例:

#include <unordered_map>
#include <iostream>
 
int main()
{
    std::unordered_map<char, std::string> my_map;
 
    // emplace 元素到unordered_map中
    my_map.emplace('a', "old_value");
 
    // 尝试 emplace 新元素
    auto [iterator, success] = my_map.try_emplace('a', "new_value");
 
    if (success) {
        std::cout << "Insertion successful\n";
    } else {
        std::cout << "Insertion failed\n";
    }
 
    // 输出键值对
    for (const auto& element : my_map) {
        std::cout << element.first << " :: " << element.second << "\n";
    }
}

输出结果为:

Insertion failed
a :: old_value

这里用到的方法和前面的例子非常类似。首先我们将一个键值对('a', "old_value")插入到map中。接着我们使用std::try_emplace()方法尝试再插入一个键值对('a', "new_value")。因为之前已经有了'a'键,所以尝试插入没有成功。最后,我们输出了unordered_map中的所有键值对,可以看到unordered_map中仍然仅有一个键值对('a', "old_value")

std::try_emplace()方法的性能比对

由于std::try_emplace()只在当键值对不存在时才插入新元素,所以它在一些情况下会比std::emplace()方法更快:

  • try_emplace()方法插入的元素存在于map中时,它不会新建一个元素,只会返回指向已有元素的迭代器。
  • try_emplace()方法能够减少不必要的构造以及复制和移动元素。

因此,在需要频繁向map中emplace元素的情况下,std::try_emplace()方法可能会比std::emplace()方法表现得更好。