【问题标题】:STL container to walk forwards and backwards [duplicate]STL容器向前和向后行走[重复]
【发布时间】:2013-01-22 08:45:44
【问题描述】:

一个基本的问题,我正在寻找适合以下用途类型的 STL 容器:

1) 支持常规前向迭代

2) 支持从列表中间删除,同时向后遍历列表,并且

3) 如果向后走时删除了某些内容,我需要停下来向前走到列表的末尾。

我使用了普通的std::list,发现从列表中的某个点向前走有点困难,但可行。我使用了 forward 和 reverse_iterator 的组合,并设法避免使用advance(因为那会很昂贵!)

这是我的代码。

#include <list>
using namespace std ;

int main()
{
  list< int > os ;
  os.push_back( 1 ) ;
  os.push_back( 2 ) ;
  os.push_back( 3 ) ;
  os.push_back( 4 ) ;
  os.push_back( 5 ) ;  

  // 1 2 3 4 5
  // should print:
  // 5: NOTHING
  // 4: 5
  // 3: 4,5
  // 2: 3,4,5
  // 1: 2,3,4,5
  for( list<int>::reverse_iterator riter = os.rbegin() ; riter != os.rend() ; ++riter )
  {
    //printf( "All the ones in FRONT of %d are:\n", riter->a ) ;
    printf( "%d:  ", *riter ) ;

    // You can't do it with a for loop.
    //for( list<O>::reverse_iterator iter = riter ; iter != os.rbegin() ; --iter )

    list<int>::reverse_iterator iter = riter ;

    if( iter != os.rbegin() ) do
    {
      --iter ; // move the iterator back.
      printf( " %d", *iter ) ;
    } while ( iter != os.rbegin() ) ;
    //else printf( " NOTHING AFTER ME" ) ;

    puts("");
  }
}

我的问题是:

  • 我是否选择了错误的容器?我应该改用deque 吗?
  • 有没有办法在内部循环中使用for 而不是do/while

【问题讨论】:

    标签: c++ list stl iteration reverse


    【解决方案1】:

    考虑到您的要求,我相信您选择list 是好的(但它是std::list,而不是stl::list)。

    vector 中间删除将使所有指向被删除元素之前的元素的指针、引用和迭代器无效;从 deque 的中间移除将使所有指针、引用和迭代器无效。

    另一方面,从list 中删除保证只会使您删除的元素的迭代器无效,因此如果您在删除元素时采取适当的措施,您可以继续向前和向后迭代。

    考虑到你的循环,我不禁指出:

    if (C) do { ... } while (C)
    

    相当于更优雅(IMO):

    while (C) do { ... }
    

    【讨论】:

    • 我不同意要求表明 std::list 是最佳选择。您也可以使用 std::vector 向前/向后迭代,而且在实践中它更快。至于失效,作为一般规则,我会避免保留对元素的引用/迭代器,尤其是在运行时修改的容器中,并且更喜欢使用容器的访问器。
    • 在大多数情况下,std::vector 确实更快,但您不会回答 IMO 的问题。 OP 询问是否考虑到他的要求,他的选择是否可以,我认为可以。我认为他有充分的理由提出这些要求。你基本上是在断言他不应该有这些要求,我相信我们没有足够的知识来说明这一点
    • std::vector 的中间移除是不行的,它需要重新分配整个数组
    • @bobobobo:实际上并没有:仅添加更多元素可能会导致完全重新分配。删除只是将所有后续元素移动一个位置,这会使迭代器、指针和引用无效,但不会导致重新分配。并且由于移动语义和数据局部性(元素位于内存的连续区域中),这提供了非常高的缓存命中率,这通常比删除小元素的列表更快,或者至少相当。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 2017-08-18
    相关资源
    最近更新 更多