std :: map,std :: set和std :: priority_queue中的比较器

std :: map,std :: set和std :: priority_queue中的比较器

问题描述:

所有这三个容器都通过const引用接受函数对象,而不是值或转发引用。这导致需要将函数对象复制到容器的内部存储器中(最多两次)。std :: map,std :: set和std :: priority_queue中的比较器

是否有复制函数对象两次的原因?与赋予用户传递任何类型的函数对象并将其构建到内部函子存储中的能力相反?这样,图书馆就更加普遍,对用户而言意想不到。


相同的理念是在push_back()功能施加 - 它们具有两个重载,一个具有const引用和一个与一个rvalue参考,因为这为用户提供了关于他们是否希望移动的值或复制多个控制价值。在一般情况下,图书馆保持高效率,而不会对用例做任何假设。

我怀疑这是一个设计决定,自从C++之前的11天以来一直在继续。改变这是标准的体面提案吗?

通常,比较器是一个非常小的对象,便于复制,而且您只需构建一次容器。额外的一次复制一次不是真的要去做。您可能不会在延迟敏感的代码中创建一堆std::map。因此,为这些容器引入更多构造函数并没有太多好处。这样的提案会是什么样子?那么你会想通过右值引用参考Allocator吗?现在我们添加了更多的构造函数。改变所有构造函数采取Compare const&而不是采取约束转发引用?现在,我们打破了ABI仍然边缘,如果有的话,获得。构造函数很复杂。我甚至不相信,如果今天设计了std::map,那么界面在这方面看起来会有所不同。如果有的话,我们可能只需要Compare而不是const&

另一方面,在主程序运行期间,push_back被用于各种类型的LOT。能够将vectoremplace转换为vector,是一个巨大的胜利。这两种情况并没有真正的可比性。

+0

为什么std :: thread构造函数接受一个由rvalue引用的函子?如果它只是在内部复制它?而且我们不会添加更多的构造函数,它只是将现有构造函数更改为通过转发引用来接受参数。虽然我不确定这是否会破坏事物。 – Curious

+0

@Curious'thread'有一个构造函数,它具有任意函数。 'map'有4个构造函数,它们需要一个'Compare'或一个'Allocator' - 你必须改变它们,这更复杂一些,并且打破ABI。 – Barry

+0

这究竟是如何打破ABI?当你传递一个非右值时,比较器就会像以前一样被复制。 – Curious