Emplacing a std::pair

Emplacing a std::pair

本文关键字:pair std Emplacing      更新时间:2023-10-16

是否有放置std::pair的方法?

std::unordered_map<int, std::pair<std::string, std::string>> my_map;
my_map.emplace(1, "foo", "bar"); // Error

当然可以插入:

my_map[2] = std::make_pair("bar", "foo");

但这难道不需要不必要的复制/移动吗?

有没有一种方法可以放置std::对?

参数需要适用于pair<int, pair<string,string>>的构造函数,即映射的value_type:

my_map.emplace(1, std::make_pair("foo", "bar"));

但这难道不需要不必要的复制/移动吗?

否;make_pair生成一对指向字符串文字的指针,然后将其用于初始化(在emplace的情况下)或分配给(在[]的情况下的)映射中包含的字符串。

在这种情况下,放置"值类型"std::pair的部分没有什么意义,因为std::string既可以有效地从C字符串转换,也可以有效地移动到映射中。简单的m.emplace( 3, std::make_pair( "bob", "alice" ) )和你99%的方式达到最佳效率。

但是,如果您有一个std::map映射到无法以这种方式有效构建的类型,则C++11为std::pair提供std::piecewise_construct,使其成为emplaced。

struct A { }; // nothing
struct C { C(C&&)=delete; }; // no copy/move
struct B { B()=delete; B(B&&)=delete; B(C&&, C&&) {}; }; // no copy/move, only annoying ctor
std::map< int, std::pair<A,B> > test;
// test.emplace( 0, std::make_pair( A{}, B{} ); // does not compile
// test.emplace( 0, std::make_pair( A{}, B{C{},C{}} ); // does not compile
test.emplace( std::piecewise_construct,
  std::make_tuple(0),
  std::forward_as_tuple(
    std::piecewise_construct,
    std::forward_as_tuple(A{}),
    std::forward_as_tuple( C{}, C{} )
  )
); // compiles!

实例

这是一种极端的情况,因为高效移动对象要常见得多。

有:

my_map.emplace(1, std::make_pair("foo", "bar"));

使用C++17,您可以使用try_emplace来实现这一点:

std::unordered_map<int, std::pair<std::string, std::string>> my_map;
my_map.try_emplace(1, "foo", "bar");