【问题标题】:Comparators in std::map, std::set and std::priority_queuestd::map、std::set 和 std::priority_queue 中的比较器
【发布时间】:2017-07-28 12:20:33
【问题描述】:

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

复制函数对象两次是否有原因?而不是让用户能够传递任何类型的函数对象并将其构建到内部函子存储中?这样库就更通用了,给用户带来的惊喜也更少。


push_back() 函数中应用了相同的理念 - 它们有两个重载,一个带有 const 引用,一个带有 rvalue 引用,因为这让用户可以更好地控制他们是要移动值还是复制值.该库在一般情况下保持高效,无需对用例做出任何假设。

我怀疑这是自 C++11 之前的日子以来一直沿用的设计决策。改变这个对标准来说是一个不错的提议吗?

【问题讨论】:

    标签: c++ c++11 c++14 move-semantics functor


    【解决方案1】:

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

    另一方面,push_back 在程序的主要运行时被大量使用,具有多种类型。能够进入vector,或emplace 进入vector,是一个巨大的胜利。这两种情况真的没有可比性。

    【讨论】:

    • 如果 std::thread 构造函数只在内部复制它,为什么它会通过右值引用接受函子呢?而且我们不会添加更多构造函数,它只会更改现有构造函数以通过转发引用来接受参数。虽然我不确定这是否会破坏事情..
    • @Curious thread 有一个可以接受任意函数的构造函数。 map 有 4 个构造函数,它们采用 CompareAllocator - 您必须全部更改,这要复杂得多,并且会破坏 ABI。
    • 这究竟是如何破坏 ABI 的?当你传递一个非右值时,比较器将像以前一样被复制。
    • 除非它不是 const。或者你没有提供分配器,现在它也不是 const。
    • 如果不是 const 它仍然会被复制,对吗?只有当它是一个右值时才会被移动
    猜你喜欢
    • 2016-05-13
    • 2012-04-25
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 2014-04-14
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多