std :: map emplace没有复制值

Dre*_*kes 48 c++ dictionary stl c++11 emplace

C++ 11 std::map<K,V>类型具有一个emplace函数,许多其他容器也是如此.

std::map<int,std::string> m;

std::string val {"hello"};

m.emplace(1, val);
Run Code Online (Sandbox Code Playgroud)

此代码的工作方式与宣传的一样,std::pair<K,V>直接安排,但它会产生副本keyval发生.

是否可以将值类型直接置于地图中?我们能比调用中的参数更好emplace吗?


这是一个更彻底的例子:

struct Foo
{
   Foo(double d, string s) {}
   Foo(const Foo&) = delete;
   Foo(Foo&&) = delete;
}

map<int,Foo> m;
m.emplace(1, 2.3, string("hello")); // invalid
Run Code Online (Sandbox Code Playgroud)

Pra*_*ian 68

您传递的参数将map::emplace被转发到构造函数map::value_type,即pair<const Key, Value>.所以,你可以使用分段施工构造std::pair,以避免中间拷贝和移动.

std::map<int, Foo> m;

m.emplace(std::piecewise_construct,
          std::forward_as_tuple(1),
          std::forward_as_tuple(2.3, "hello"));
Run Code Online (Sandbox Code Playgroud)

现场演示

  • 这非常难看,但你拿走了你得到的东西:) (2认同)

Jam*_*ess 19

在C++ 17中,使用该try_emplace方法可以更容易地实现这一点.

map<int,Foo> m;
m.try_emplace(1, 2.3, "hello");
Run Code Online (Sandbox Code Playgroud)

标准库的这一新增内容已在N4279论文中介绍,并且应该已在Visual Studio 2015,GCC 6.1LLVM 3.7(libc ++库)中得到支持.

  • 是的,“try_emplace()”确实是最好的解决方案。特别是,“emplace()”总是在堆上构造一个键值对。因此,如果确实在表中找到了该键,“emplace()”将再次删除刚刚新建的键值对。相反,“try_emplace”按照预期的顺序执行所有操作:检查它们的 Key 是否存在,如果存在,则返回该键值对的迭代器。如果没有,则它将新的键和值放入容器中。 (3认同)