2017-05-26 181 views
67

我有我使用如何获得列表中的倒数第二个元素?

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

一个std::list<double> foo;

但总是给我的penultimate任意值。

我在做什么错?

+25

最后,从一个新的用户一个很好的书面质询。有一个upvote! – Bathsheba

+29

对于像我这样不记得“倒数第二”是什么意思的人来说,这意味着倒数第二个 – Justin

+1

@Mehrdad OP绝对不想这样。特别是因为该迭代器不指向任何元素。 –

回答

67

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

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

rbegin()返回反向迭代,所以++是在容器向后移动运营商。请注意,我也放弃了多余的括号:这不符合每个人的口味。

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


做保留的最小尺寸检查您当前拥有。

+0

为什么你可以将operator ++应用于临时右值呢?我认为++, - 等仅适用于左值 – cat

+0

@cat对于允许它的迭代器,至少就我所知,“operator ++”通常是一个成员函数。没有规则规定成员函数只能在左值被调用,[除非成员函数被引用为'&'](http://coliru.stacked-crooked.com/a/888d3b7a1253866b)。 –

+0

OP没有移动到'foo.end()'这是一个完全有效的迭代器(虽然它不能被解引用),而'foo.rbegin() - 1'是无效的,甚至在试图解引用它之前。 –

10

我只是做*--(--foo.end());不需要反向迭代器。它也不那么混乱。

+3

如果你想知道(就像我做过的那样),这是两次递减,因为末尾迭代器指向一个虚构的过去末端元素。 – Andreas

25

最明显的方式,在我看来,就是用为此目的设计(C++ 11)的结构:

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

只有在C++ 11中添加了所有函数的情况下才能清除,如果想让代码向后不兼容,这是一个好主意;)我甚至不知道存在“std :: prev”! – Mehrdad

+0

在我看来,这绝对是最清晰的解决方案,因为它涉及最少数量的话务员呼叫,避免了接受答案的倒退/前转混淆。 – ApproachingDarknessFish

+3

6年前C++ 11问世。如果用户想要传统方法,他们应该要求一个。 –

相关问题