Namespaces
Variants

std::map<Key,T,Compare,Allocator>:: try_emplace

From cppreference.net

template < class ... Args >
std:: pair < iterator, bool > try_emplace ( const Key & k, Args && ... args ) ;
(1) (C++17 起)
template < class ... Args >
std:: pair < iterator, bool > try_emplace ( Key && k, Args && ... args ) ;
(2) (C++17 起)
template < class K, class ... Args >
std:: pair < iterator, bool > try_emplace ( K && k, Args && ... args ) ;
(3) (C++26 起)
template < class ... Args >
iterator try_emplace ( const_iterator hint, const Key & k, Args && ... args ) ;
(4) (C++17 起)
template < class ... Args >
iterator try_emplace ( const_iterator hint, Key && k, Args && ... args ) ;
(5) (C++17 起)
template < class K, class ... Args >
iterator try_emplace ( const_iterator hint, K && k, Args && ... args ) ;
(6) (C++26 起)

如果容器中已存在与 k 等效的键,则不执行任何操作。否则,将使用键 k 和通过 args 构造的值向容器中插入新元素。此时:

1) 行为类似于 emplace ,区别在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( k ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
2) 行为类似于 emplace ,区别在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( std :: move ( k ) ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
3) 行为类似于 emplace ,区别在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( std:: forward < K > ( k ) ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
4) 行为类似于 emplace_hint ,不同之处在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( k ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
5) 行为类似于 emplace_hint ,区别在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( std :: move ( k ) ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
6) 行为类似于 emplace_hint ,不同之处在于元素被构造为
value_type ( std:: piecewise_construct ,

std:: forward_as_tuple ( std:: forward < K > ( k ) ) ,

std:: forward_as_tuple ( std:: forward < Args > ( args ) ... ) )
1-6) value_type 无法通过对应表达式 原位构造 map 中,则行为未定义。
3) 此重载仅在满足以下所有条件时参与重载决议:
如果 equal_range ( u. first ) == equal_range ( k ) false ,则行为未定义,其中 u 是要插入的新元素。
6) 此重载仅当限定标识符 Compare :: is_transparent 有效且表示一个类型时才参与重载决议。
如果 equal_range ( u. first ) == equal_range ( k ) false ,则行为未定义,其中 u 是要插入的新元素。

不会使任何迭代器或引用失效。

目录

参数

k - 用于查找且未找到时插入的键
hint - 指向新元素将插入位置之前的迭代器
args - 要转发给元素构造函数的参数

返回值

1-3) emplace 相同:
返回一个由迭代器和布尔值组成的 pair,其中迭代器指向被插入元素(或阻止插入的元素),布尔值当且仅当插入成功时被设置为 true
4-6) emplace_hint 相同:
返回指向被插入元素的迭代器,或指向阻止插入的元素的迭代器。

复杂度

1-3) emplace 相同:
时间复杂度与容器大小的对数成正比。
4-6) emplace_hint 相同:
通常与容器大小成对数复杂度,但若新元素恰在 hint 前插入则摊还常数复杂度。

注解

insert emplace 不同,这些函数在插入未发生时不会从右值参数移动,这使得操作值为仅移动类型的映射变得容易,例如 std:: map < std:: string , std:: unique_ptr < foo >> 。此外, try_emplace 将键和 mapped_type 的参数分开处理,这与需要构造 value_type (即 std::pair )参数的 emplace 不同。

重载版本 ( 3 ) ( 6 ) 可以在不构造 Key 类型对象的情况下调用。

功能测试 标准 功能
__cpp_lib_map_try_emplace 201411L (C++17) std::map::try_emplace , std::map::insert_or_assign
__cpp_lib_associative_heterogeneous_insertion 202311L (C++26) 有序 无序 关联 容器 中剩余成员函数的异构重载。重载 ( 3 ) ( 6 )

示例

#include <iostream>
#include <string>
#include <map>
#include <utility>
void print_node(const auto& node)
{
    std::cout << '[' << node.first << "] = " << node.second << '\n';
}
void print_result(auto const& pair)
{
    std::cout << (pair.second ? "inserted: " : "ignored:  ");
    print_node(*pair.first);
}
int main()
{
    using namespace std::literals;
    std::map<std::string, std::string> m;
    print_result(m.try_emplace("a", "a"s));
    print_result(m.try_emplace("b", "abcd"));
    print_result(m.try_emplace("c", 10, 'c'));
    print_result(m.try_emplace("c", "Won't be inserted"));
    for (const auto& p : m)
        print_node(p);
}

输出:

inserted: [a] = a
inserted: [b] = abcd
inserted: [c] = cccccccccc
ignored:  [c] = cccccccccc
[a] = a
[b] = abcd
[c] = cccccccccc

参见

(C++11)
原地构造元素
(公开成员函数)
使用提示原地构造元素
(公开成员函数)
插入元素 或节点 (C++17 起)
(公开成员函数)