【问题标题】:is there prettier syntax for a c++ iterator?c++ 迭代器有更漂亮的语法吗?
【发布时间】:2011-08-16 02:35:20
【问题描述】:

在 C++ 中是否有更漂亮/更简洁的方式来使用迭代器?从我看到的教程中,我要么在任何地方设置 typedef(对于很多一次性 for 循环来说,这样做很乏味):

typedef std::vector<std:pair<int, int> >::iterator BlahIterator;

或有冗长的寻找循环,如:

for (std::vector<std:pair<int, int> >::iterator it = ... ) ...

有没有更好的办法?

【问题讨论】:

  • 是的,使用 C++11 并说auto!
  • 如果可以完全避免循环语法,使用 STL 算法也有帮助。
  • 另一个想法是typedef你的容器。这使得这样的迭代器声明不那么难看并且更易于维护。 drdobbs.com/184401853

标签: c++ iterator design-patterns syntactic-sugar


【解决方案1】:

在 C++11 中,您可以将基于范围的 for 循环与 auto 关键字结合使用:

for (auto& it : v) ...

【讨论】:

    【解决方案2】:

    通过boost,您可以使用FOR_EACH 宏。

    typedef pair<int, int> tElem;
    BOOST_FOREACH( tElem e, aVector )
    {
        cout << e.first << " " << e.second << '\n';
    }
    

    【讨论】:

    • 使用 C++11 甚至 更漂亮 BOOST_FOREACH( const auto&amp; i, aVector )
    • 使用纯 C++11 更加更漂亮for(const auto&amp; i : aVector) {}
    • @In silico,它应该是一个答案(看看你已经得到了多少赞成票)。
    【解决方案3】:

    算法可以解决这个特定问题。
    尤其是新的 lambda 函数。

    std::for_each(c.begin(), c.end(), Action()); /* Where Action is your functor */
    

    或者使用 lambda:

    std::for_each(c.begin(), c.end(), [](type const& e) { /* Stuff */ });
    

    注意:不要陷入使用 std::for_each 替换所有循环的陷阱。有一大堆算法使用迭代器,允许您根据容器的内容进行操作或执行操作。

    【讨论】:

    • std::for_each(x.begin(), x.end(), ...) 的形式似乎很常见,我很惊讶没有更容易输入/阅读它的速记...
    • @NetMage:现在有。基于范围的 for 语句是执行此操作的新方法。
    • 对我来说,这感觉像是 for 声明,而不是函数式编程风格的改进/替代。带有 LINQ 的 C# 两者兼而有之。
    • @NetMage C++ 语言对实现没有任何限制。所以for(;;)for(:)std::for_each() 可以根据需要在底层进行优化。至于 functional programming style 不确定这有什么关系,尤其是因为 C++ 是多范式。
    • 如何在链中使用for(:)?
    【解决方案4】:

    使用 c++0x 你可以使用 auto 关键字:

    for (auto i = v.begin(); i != v.end(); ++i) {}
    

    【讨论】:

    • 只是好奇:.begin() 方法可以返回 iteratorconst_iterator。如何使用 c++0x 语法告诉编译器我想要const_iterator
    • @Michał:使用.cbegin().cend() 指定const_iterators
    • @Michal:这取决于v 的常量。如果v 不是const,则选择非常量重载。正如 Blastfurnace 所说,C++0x 引入了一对新的 cbegin / cend 以允许从非常量容器中获取 const_iterator 而无需黑客攻击。
    【解决方案5】:

    我通常使用以下命名模式:

    typedef std::pair<int, int> Blah;
    typedef std::vector<Blah> Blahs;
    

    然后使用Blahs::iterator,即我不命名迭代器,而是命名容器(通常是其中包含的东西)。
    typedef 是一种非常有用的抽象机制。

    请注意,“Blah”的向量称为“Blahs”(即只是复数),而不是“BlahVector”,因为具体的容器无关紧要。

    【讨论】:

      【解决方案6】:

      一种可能性是将您的循环(或使用迭代器的任何代码)编写成自己的小型通用算法。通过使其成为模板,编译器可以/将自动推断迭代器类型:

      template <class T>
      do_something(T begin, T end) { 
          for (T pos = begin; pos != end; ++pos) 
              do_something_with(*pos);
      }
      

      【讨论】:

        【解决方案7】:

        我通常会定义这个,尽管有人告诉我我会为此付出代价:

        #define forsn(i, s, n) for(int i = (s); i < (n); ++i)
        #define forn(i, n) forsn(i, 0, n)
        #define forall(it, g) for(typeof g.begin() it = g.begin(); it != g.end(); ++it)
        

        然后,从 0 循环到 n,这是一个常见任务,我说 forn(i, n) foo(i);,并循环任何标准容器 c,我说 forall(it, c) foo(it); 请注意 typeof 是标准的 GCC 扩展。

        【讨论】:

        • 你当然是!当您可以使用模板化函数 + 谓词时,您依赖宏 + 编译器扩展 :)
        猜你喜欢
        • 1970-01-01
        • 2023-02-07
        • 2020-11-21
        • 2019-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-22
        相关资源
        最近更新 更多