std::map 的 emplace() 如何避免过早构建?

How does std::map's emplace() avoid premature construction?

我对 std::mapsemplace() 的实施感到困惑。 emplace() 是一个具有以下声明的可变参数模板函数:

template <class Args...>
iterator emplace( Args&&... args );

据我了解,emplace() 完全避免构造其 value_type,即 std::pair<const key_type,mapped_type>,而是就地构造对象。我假设这意味着该对象仅在创建新地图节点时构造一次。该对象永远不会被复制或移动。

我不明白的是std::map如何在构造键值对之前找到添加新条目的正确位置。据我所知,std::map 需要访问密钥,但密钥包含在 args 中,并且只能在构建键值对后访问。

我一定是误解了 emplace() 的某些方面。 std::map 是否真的避免了键值对的构造?如果是这样,它如何避免 move/copy 操作?或者有其他方法可以访问 args 中的密钥吗?

emplace 构造 in-place 对,将参数转发给它的构造函数;它不会避免 element_type 构造,它只是避免了与 insert 相比无用的临时对的一个副本。在这方面,它与其他容器一样:emplace 类似于 insert,但是如果接收到 ready-made element_type 以在容器内复制或移动,它会接收在其目标位置构造 element_type 的参数。

进一步说明:如果您在构造对时无论如何调用 emplace(key, value) keyvalue copied/moved。只是,如果你做了 insert(make_pair(key, value)),不仅 keyvalue 在创建临时对参数时会变成 copied/moved,而且对本身也需要在地图节点中移动。

I don't think that is what OP intends to ask for. The intended question to me seems to be how std::map can find the correct location to insert the new element if it can't construct the key prior to searching for the location, e.g. if the first argument to emplace is not the key type itself.

在那种情况下,对于 std::map 没有太大问题:首先你可以构造一个节点(它包含对和指向其他节点的各种指针,并在堆上有自己的分配) , 然后你可以把它放在 RB 树的正确位置(归结为几个指针赋值)。

嗯,IIRC,std::mapstd::unrodered_map 使用 tree-like 结构,有很多小节点相互指向。因此,一旦构建了对 - 它不必移动到任何地方,地图只需要从某个地方指向它。