【问题标题】:How can I get the penultimate element in a list?如何获取列表中的倒数第二个元素?
【发布时间】:2017-10-27 15:21:05
【问题描述】:

我有一个std::list<double> foo;

我正在使用

if (foo.size() >= 2){
    double penultimate = *(--foo.rbegin());
}

但这总是给我penultimate的任意值。

我做错了什么?

【问题讨论】:

  • 最后,一个新用户写的很好的问题。投赞成票!
  • 对于像我这样不记得“倒数第二个”是什么意思的人来说,它意味着倒数第二个
  • @Mehrdad OP 绝对不希望这样。特别是因为该迭代器不指向任何元素。
  • 我会加入,除非你知道你特别需要一个链表并且可以清楚地说明原因,否则永远不要使用std::list。首选std::vector

标签: c++ stl stdlist


【解决方案1】:

而不是递减rbegin,你应该递增它,如下所示:1

double penultimate = *++foo.rbegin();

因为rbegin() 返回一个反向迭代器,所以++ 是容器中向后移动的操作符。请注意,我还删除了多余的括号:这不符合每个人的口味。

目前您的程序的行为是未定义,因为您实际上正在移动到end(),并且您不能取消引用它。输出的任意性质是这种未定义行为的表现。


1请保留您目前拥有的最小尺寸检查。

【讨论】:

  • 为什么仍然可以将 operator++ 应用于临时右值?我认为 ++、-- 等仅用于左值
  • @cat 对于允许它的迭代器,operator++ 通常是一个成员函数,至少据我所知。没有规定只能在左值上调用成员函数,unless the member function is ref-qualified as &
  • OP 没有移动到 foo.end(),这是一个完全有效的迭代器(尽管它不能被取消引用),而 foo.rbegin()-1 是无效的,即使在尝试取消引用它之前也是如此。
【解决方案2】:

在我看来,最清晰的方法是使用为此目的设计的构造 (C++11):

double penultimate = *std::prev(foo.end(), 2)

【讨论】:

  • 只有在你跟上 C++11 中添加的所有函数的情况下才清除,如果你想让你的代码向后不兼容是个好主意;) 我什至不知道 std::prev存在!
  • 在我看来,这绝对是最清晰的解决方案,因为它涉及的接线员呼叫次数最少,并且避免了接受答案的前后混淆。
  • C++11 于 6 年前问世。如果用户想要一个传统的方法,他们应该要求一个。
【解决方案3】:

我会做*--(--foo.end());不需要反向迭代器。它也不那么令人困惑。

【讨论】:

  • 如果你想知道(像我一样),它是两个递减,因为结束迭代器指向一个虚构的过去元素。
猜你喜欢
  • 2017-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
相关资源
最近更新 更多