【问题标题】:Iterate backwards using iterators使用迭代器向后迭代
【发布时间】:2016-11-19 09:10:10
【问题描述】:

为了简化我的问题,我将使用std::string::iteratorstd::string::reverse_iterator,但问题一般是关于迭代器的。

是否有任何特殊原因需要使用以下循环向后迭代:

std::string s = "something";
for (std::string::reverse_iterator it = s.rbegin(); it != s.rend(); ++it)

而不是这个:

std::string s = "something";
std::string::iterator it = in.end();
while(it!=in.begin())
{
    it--;
   //do something
}

【问题讨论】:

    标签: c++ string iterator


    【解决方案1】:

    反向迭代器允许您重用通用代码,因为您可以像对待普通迭代器一样对待它们,调用++ 进行反向操作。例如:

    #include <iostream>
    #include <string>
    
    template <class Iterator>
    void printAll(Iterator begin, Iterator end)
    {
        for (auto it = begin; it != end; ++it) // ++ can mean "go backwards"
                                               // if Iterator is a reverse
                                               // iterator
        {
            std::cout << *it << "\n";
        }
    }
    
    int main()
    {
        std::string s = "123";
        printAll(s.begin(), s.end());   // prints 1, 2, 3
        printAll(s.rbegin(), s.rend()); // prints 3, 2, 1
    }
    

    请注意,您无需使用 --printAll 编写反向版本。

    现在,考虑&lt;algorithm&gt; 中的所有函数。反向迭代器的存在意味着您可以轻松地以反向方式使用它们。比如有std::copy_n,但没有std::reverse_copy_n,但是有了反向迭代器,就没有必要了,因为你可以这样写:

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <iterator>
    
    int main()
    {
        std::string input = "abcdef";
        std::string output;
        std::string output_reversed;
    
        // copy the first 3 elements:
        std::copy_n(input.begin(), 3, std::back_inserter(output));
    
        // copy the first 3 elements going backwards, starting at the last one:
        std::copy_n(input.rbegin(), 3, std::back_inserter(output_reversed));
    
        std::cout << output << "\n";          // prints abc
        std::cout << output_reversed << "\n"; // prints fed
    }
    

    对于非通用代码,例如在您的问题中,这更像是一个样式问题,很少有技术上合理的论据来选择一个而不是另一个。

    【讨论】:

    • 这是一个很好的答案,因为它实际上不仅回答了问题(一个完全正确的答案应该是 No),而是更基本的(更好) 问题reverse_iterator 有什么意义?
    【解决方案2】:

    由于 begin() 指向第一个成员,而 end() 指向最后一个成员,这就是干净的代码(因为在使用非反向迭代器的情况下,您将首先执行迭代器递减,然后你想要执行的代码,然后你将迭代器与 begin() 进行比较,但这是错误的, 因为 begin() 指向一个现有的第一个元素。

    std::vector::end() at cplusplus.com

    【讨论】:

    • in.begin()-1不,不,不,一千次没有。
    • 我不推荐它,但有时可以。
    • @sandyre 我相信我的 while 循环完成了我测试以来的预期效果。
    • 那么主要原因是第一种方式比第二种方式更优雅清晰?
    • @theVoid 基本上是的。你的循环工作得很好,对不起我的标记,删除它。
    猜你喜欢
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    相关资源
    最近更新 更多