【问题标题】:Why set/map emplace_hint does not return a boolean为什么 set/map emplace_hint 不返回布尔值
【发布时间】:2015-10-06 12:27:22
【问题描述】:

根据cppreferencestd::setstd::mapemplace 函数都返回一个std::pair<iterator,bool>,并带有一个bool 值来说明插入是否实际发生。

但是,emplace_hint 会返回一个 iterator 给插入的元素,或者如果插入没有发生,则返回给 set 或 map 中的现有元素。这里没有bool 值。

这些类似功能的界面有什么不同的原因吗?

更新

函数insert 仅在未提供提示时返回bool 值。这与emplaceemplace_hint 的行为一致。那么问题来了:在给出提示时是否有任何理由不返回bool

我只能认为可能有一些性能原因,因为用户通常在lower_bound/upper_bound操作后提供提示,所以插入肯定会发生。

【问题讨论】:

  • 如果为插入提供了提示,无论是insert还是emplace_hint都只返回迭代器(状态没有bool),所以这个行为是相当一致的
  • 确实如此。我会更新我的问题。
  • 提示函数可能会简化效率回报。 emplace_hint 旨在用于您知道在哪里执行插入的情况,如果使用正确,它实际上是 O(1) 操作,而不是 O(log2(n))。当您花费O(log2(n)) 时,构建和返回该对的增量成本很小(相对而言),但如果您有意使用为您提供O(1) 的超优化方法,您可能不希望这样(诚然很小)高架。它会返回一个iterator,因此您可以检查内容(或者只是比较 size 前后的内容)。
  • 也就是说,效率只是一个猜测。在 C++11 之前,根据实现和编译器,返回 std::pair<iterator, bool> 之类的对象的增量成本可能比仅返回 iterator 高得多。在 C++11 中无关紧要(其中命名的局部变量可以通过直接构造返回到它们的调用者中,而不是复制构造和破坏),但 emplace_hint 可能遵循早于 C 的早期提示函数的引导++11.

标签: c++ c++11 stl


【解决方案1】:

emplace_hint 这样做可能是为了与暗示的 insert 保持一致:emplaceinitially proposed 作为一对重载,镜像 insert,但暗示的重载在 LWG 763 之后重命名,尽管 Josuttis 想要改为rename the non-hinted version

关联容器的提示insert 接受一个迭代器和一个值并返回一个迭代器,以便与通用代码中顺序容器上的常规insert 兼容。正如 Josuttis 的书中提到的那样。 std::inserter

利用了这种兼容性

【讨论】:

    【解决方案2】:

    确定 emplace 是否发生的最简单方法是将地图的 size() 存储在变量中并测试在 emplace_hint() 之后该大小是否增加:

    auto oldsz = myMap.size();
    myMap.emplace_hint(it, args...);
    if(myMap.size() > oldsz) {
        // emplace was accepted
    } else {
        // the emplace was rejected, as it would have overwritten an element
    }
    

    同样的代码也可以用于insert_or_assign(),如果新的值应该覆盖旧的值以防已有的键。

    【讨论】:

    • 另外,map::size() 以恒定时间运行,以防您担心性能。
    猜你喜欢
    • 2020-03-21
    • 1970-01-01
    • 2014-02-07
    • 2014-03-20
    • 1970-01-01
    • 2020-07-04
    • 2013-08-10
    • 1970-01-01
    • 2019-10-04
    相关资源
    最近更新 更多