【问题标题】:Why is the reverse iterator .rbegin() prevented from being used as a position of the elemet to be erased?为什么阻止将反向迭代器 .rbegin() 用作要擦除的元素的位置?
【发布时间】:2021-03-18 20:21:21
【问题描述】:

std::map.rbegin() 的反向迭代器返回包含std::map 中最大 key_type 的元素的位置。
可以使用map.rbegin() 返回的位置访问具有最大 Key 的元素,如下所示:
map.rbegin()->first

但是map.rbegin()返回的位置不能用来擦除这个元素。

为什么我可以访问但不能删除相同的位置?

std::map <unsigned int, std::string> map;

map.emplace(5, "aaa");
map.emplace(7, "bbb");
map.emplace(3, "ccc");

cout << map.rbegin()->first << " : " << map.rbegin()->second << endl;       //Reverse iterator works for accessing the element

map.erase(map.rbegin());      //Erase the largest element in the map - Error C2664 converting argument 1 from 'std::reverse_iterator<std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>' to 'std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>'    
map.erase(std::prev(map.end()));    //Erase the largest element in the map - WORKS
map.erase(std::prev(map.rbegin().base()));  //Erase the largest element in the map - WORKS

在我看来,如果一个函数/方法需要一个迭代器来获得只有一个位置,那么它应该不管它是哪种迭代器。 如果该迭代器描述的不仅仅是一个位置(例如方向,也是......),事情会有所不同

注意:我没有问“How to call erase with a reverse iterator?”,我在代码的最后一行提供了这个操作的解决方案。
我在问为什么我不能用反向迭代器擦除。也就是说,如果 STL 只需要使用它来获取要擦除的一个元素的位置,为什么不简单地将 std::map::reverse_iterator 转换为 std::map:iterator

【问题讨论】:

  • 简单地说,std::map::erase 没有反向迭代器的重载。它接受map::iteratormap::const_iteratormap::key_type。这些都不是反向迭代器类型。
  • 一个“混搭”接口很容易出错,如果每个函数都需要在反向和“正常”迭代器上重载,它会使库变得非常复杂。 (一个有四个迭代器参数的函数可能需要十六个重载,如果你没有提供所有的重载,至少会有一个人会因为没有包含他们想要的组合而生气。)
  • 它并不能真正解决你的问题,但是反向迭代器有一个 base 函数,它返回一个正向迭代器 + 1。(map.rbegin().base() == map.end())
  • @super TIL。非常有用的功能,谢谢。
  • 我看到你已经编辑了你的问题以链接到“如何”目标,所以我也添加了一个“为什么”目标。不幸的是,“为什么”目标已作为“如何”目标的欺骗而被关闭,而“为什么”目标的现有答案并不能真正回答这个问题。

标签: c++ iterator c++17 c++-standard-library reverse-iterator


【解决方案1】:

为什么阻止将反向迭代器 .rbegin() 用作要擦除的元素的位置?

因为erase的参数类型不是reverse_iterator,而是iterator。这些是不同的类型。

为什么我可以访问但不能删除相同的位置?

知道对象在内存中的位置(当你可以访问一个对象时你知道的)通常不足以访问包含该元素的数据结构。

【讨论】:

  • 但是在这种情况下,这个迭代器对于访问包含这个元素的数据结构已经足够了。 cout &lt;&lt; map.rbegin()-&gt;first 的成功执行证明了这一点
  • @GeorgeRobinson 这是真的。另一方面,std::pair&lt;std::map &lt;unsigned, std::string&gt;*, unsigned&gt; 也足以访问数据结构。然而,由于某种原因,您不能将其传递给erase。原因与您不能传递reverse_iterator 的原因相同:因为参数的类型是iterator,既不是那对,也不是reverse_iterator
  • 是的,erase() 的参数类型不同,但真正的问题是,当反向迭代器包含访问数据结构所需的所有信息时,为什么没有为反向迭代器提供重载。 std::map 的代码也实现了这两种类型的迭代器,但它没有实现 std::pair
  • @GeorgeRobinson 我不能代表 Stepanov。我不知道这种选择的理由是否记录在任何地方。
猜你喜欢
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
  • 2012-04-22
  • 2014-06-11
相关资源
最近更新 更多