【问题标题】:Visual c++ "for each" portabilityVisual c++“为每个”可移植性
【发布时间】:2010-09-16 21:03:40
【问题描述】:

我最近才发现 Visual C++ 2008(也许还有更早的版本?)在 stl 列表等上支持 for each 语法以促进迭代。 例如:

list<Object> myList;

for each (Object o in myList)
{
  o.foo();
}

我很高兴发现它,但是当有人决定我需要能够用 gcc 或其他编译器编译我的代码时,我担心可移植性。这种语法是否得到广泛支持,我可以在不担心可移植性问题的情况下使用它吗?

【问题讨论】:

    标签: c++ visual-c++ stl foreach


    【解决方案1】:

    我不会用那个。虽然这是一个诱人的功能,但其语法与即将推出的 C++0x 标准不兼容,该标准使用:

    list<Object> myList;
    
    for (Object o : myList)
    {
       o.foo();
    }
    

    做同样的事情。

    【讨论】:

      【解决方案2】:

      For each 不是标准的 C 或 C++ 语法。如果您希望能够在 gcc 或 g++ 中编译此代码,则需要创建一个迭代器并使用标准 for 循环。

      量子皮特

      [编辑] 这似乎是 MS Visual C++ 中引入的一个新特性,所以这绝对是不可移植的。参考:http://msdn.microsoft.com/en-us/library/xey702bw%28VS.80%29.aspx [/edit]

      【讨论】:

        【解决方案3】:

        有一个很好的便携替代品:Boost.Foreach。只需将此标头转储到您的项目中,您就可以按如下方式编写循环:

        list<Object> myList;
        
        BOOST_FOREACH(Object o, myList)
            o.foo();
        

        【讨论】:

          【解决方案4】:

          如果您想使用 foreach,同时又不想添加额外的依赖项(例如 Boost) - 此宏将帮助您:

          #define VAR(V,init) __typeof(init) V=(init)
          #define FOREACH(I,C) for(VAR(I,(C).begin());I!=(C).end();I++)
          
          std::vector<int> numbers;
          
          FOREACH(I, numbers)
          {
              std::cout << *I << std::endl;
          }
          

          【讨论】:

            【解决方案5】:

            Visual C++“for each”不是标准的 C++,这意味着您将无法在其他编译器(例如 g++)上编译您的代码。然而,STL 提出了std::for_each,但它的语法不那么直观。这是它的原型:

            template <class InputIterator, class UnaryFunction>
            UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
            

            它需要两个定义有效范围的迭代器,并将一元函数(或函子) f 应用于此范围内的每个对象。 您可以像这样使用 std::for_each 重写您的示例:

            void foo(Object o)
            {
              o.foo();
            }
            ...
            list<Object> myList;
            
            std::for_each(myList.begin(), myList.end(), foo);
            

            但是,如果您想接近 for each 构造的经典语法,并且可以使用 Boost,则可以使用BOOST.FOREACH,它可以让您编写

            list<Object> myList;
            
            BOOST_FOREACH(Object o, myList)
            {
                o.foo();
            }
            

            【讨论】:

            • 注意:即使在 VS 2005/2008 中,对于每个(a 中的 b)似乎都是 CLR - 您不能在本机代码中使用它,只有在针对 .NET 时,才能使每个(甚至“不那么便携”) ”。否则我认为你的回答很好。
            • 另外请注意,如果你使用的是 VS2010,你有 lambdas 并且 std::for_each() 突然变得容易阅读了。
            【解决方案6】:

            Boost 库有一个可移植的ForEach imlementation

            【讨论】:

              【解决方案7】:

              您的代码确实不可移植。

              以下内容适用于 C++ 0x 标准和 Visual C++ 2010(据我所知,它不支持新的“ranged for”语法)。

              #define for_each(_ITER_, _COLL_) for (auto _ITER_ = _COLL_.begin(); \
                  _ITER_ != _COLL_.end(); _ITER_++)
              

              现在你可以写了:

              list<Object> myList;
              
              for_each (o, myList)
              {
                o.foo();
              }
              

              将此与http://www.boost.org/doc/libs/1_48_0/boost/foreach.hpp 处的 BOOST_FOREACH 宏代码进行比较,这不仅复杂,而且还依赖于其他 boost 库。

              【讨论】:

                【解决方案8】:

                我也推荐 BOOST_FOREACH。我通常按​​照以下方式创建一个宏:

                #define _foreach(x,y) BOOST_FOREACH(x,y)
                

                这往往会增加可读性。不过,您必须小心与其他 foreach 实现的冲突。例如,Qt 提供了一个“foreach”,还有 std::for_each。

                我发现 std::for_each 实际上并没有节省太多时间,因为您最终会制作大量一次性函数对象来提供给 for_each 调用。使用 STL 迭代器制作标准 for 循环通常同样快。

                【讨论】:

                • 在 Boost.Foreach 文档中,他们明确建议不要使用您编写定义的方式。改为写“#define _foreach BOOST_FOREACH”。
                • 我喜欢将它保留为 BOOST_FOREACH 只是因为它提醒它是一个宏扩展并且要小心我放入其中的内容。
                【解决方案9】:

                我投票给卢克,

                坚持使用标准的 STL 算法,到目前为止你会做得更好。 STL 算法可以让您的生活变得非常轻松、高效和安全。看看现成的算法,如 find_if、count、count_if、sort、transform 等......

                第 5 点以后... http://www.sgi.com/tech/stl/table_of_contents.html

                Boost 很酷,但是如果您只将它用于 FOR_EACH 宏,那么在开发/构建环境设置方面就太麻烦了。

                当标准 c++ / stl 无法以“简单”的方式解决问题时,请使用 boost。

                【讨论】:

                  猜你喜欢
                  • 2010-10-08
                  • 2013-01-12
                  • 2011-08-11
                  • 1970-01-01
                  • 2012-08-15
                  • 2010-10-29
                  • 2023-03-05
                  • 2021-04-10
                  • 2013-05-16
                  相关资源
                  最近更新 更多