【问题标题】:Calling std::map::emplace() and avoiding unnecessary constructions调用 std::map::emplace() 并避免不必要的构造
【发布时间】:2013-12-29 21:40:28
【问题描述】:

我有一个std::map,它的键是std::string,值是我自己定义的类型。

假设我有以下代码:

std::map<std::string, MyType> mymap;
std::string str1("test");
MyType value(pars); //I want value to be moved

mymap.emplace(std::make_pair(str1, std::move(value))); //A
mymap.emplace(str, std::move(value)); //B

假设 std::map 存储对,我猜 A 会进一步调用 std::pair 构造函数 (make_pair),然后再次调用 std::pair 移动构造函数(带有右值参数的就地构造)。

而且我认为 B 只会生成对 std::pair 构造函数的调用。

那么我们可以说 B 优于 A 以避免不必要的结构吗?

【问题讨论】:

  • 你尝试过std::pair的分段构造吗?
  • 不,这只会使我的问题复杂化。但也许有人想详细说明这一点。
  • 我不确定分段构造在这里有什么帮助;我宁愿说forward_as_tuple 可以用来代替make_pair 来防止对的移动构造。
  • @jbgs 你是对的,已修复。

标签: c++ c++11


【解决方案1】:

根据http://www.cplusplus.com/reference/map/map/emplace/

如果其键是唯一的,则在地图中插入一个新元素。这个新元素是使用 args 作为构造 value_type(它是对类型的对象)的参数就地构造的……通过调用 allocator_traits::construct 并转发 args 就地构造元素。

因此,在选项 A 中,您首先构造一对 emplace 将转发给 pair 的构造函数(作为右值),然后构造函数将执行移动构造。

选项 B 将 strstd::move(value) 的返回值转发给 pair 的构造函数。

所以是的,选项 A 构造 2 对,而选项 B 仅构造 1。

【讨论】:

  • “然后将执行复制构造” 一个 move 构造。转发的对是一个右值。
  • @LightnessRacesinOrbit 我相信 “一些实现” 是轻描淡写的。在你的回答中你写:“所有三个主流工具链”(gcc、clang、msvc)。顺便问一下,有没有关于这个问题的消息?
  • @Ali:好吧,我不想说“全部”。不,据我所知:(关于标准讨论的讨论尚无定论。
  • @LightnessRacesinOrbit 如果“所有三个主流工具链”仍然成立,那么不要害怕大声说出来。很遗憾,讨论没有结果。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多