Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Is std::map+;std::tr1::bind+;标准算法值得吗?_C++_Algorithm_Stl_Bind - Fatal编程技术网

C++ Is std::map+;std::tr1::bind+;标准算法值得吗?

C++ Is std::map+;std::tr1::bind+;标准算法值得吗?,c++,algorithm,stl,bind,C++,Algorithm,Stl,Bind,这是我的后续行动。Scott Meyers关于只写代码的警告一直萦绕在我的脑海中。原则上,我喜欢使用标准算法访问std::map的键或值,但所需的语法有点巴洛克风格。假设我想将贴图的所有关键点转储到一个向量。鉴于以下声明 typedef std::map<int, int> MyMap; MyMap m; std::vector<int> v; 选项2: 选项1更标准,但我必须在精神上分解它以了解发生了什么。选项2似乎更容易阅读,但可能会造成较小的运行时损失。我没有伤到

这是我的后续行动。Scott Meyers关于只写代码的警告一直萦绕在我的脑海中。原则上,我喜欢使用标准算法访问std::map的键或值,但所需的语法有点巴洛克风格。假设我想将贴图的所有关键点转储到一个向量。鉴于以下声明

typedef std::map<int, int> MyMap;
MyMap m;
std::vector<int> v;
选项2:

选项1更标准,但我必须在精神上分解它以了解发生了什么。选项2似乎更容易阅读,但可能会造成较小的运行时损失。我没有伤到CPU时间,所以我倾向于选择2。你们同意吗?有第三种选择我应该考虑吗?< 在写这个问题的过程中,我得出结论,(对于我的项目来说)读取std::map的键的最好方法是将它们存储在一个侧容器中,然后迭代。然而,可维护性问题仍然存在。

我说,坚持2)

为了提高性能,可以从循环中获取
m.end()
,并在向量中保留空间


不能等待C++0x和基于范围的for循环;这会让你的循环变得更好。

清晰总是胜过聪明。做你以后能读到的事


并非只有您认为标准代码有点迟钝。下一个C++标准将介绍,以便你可以用标准的算法编写更清晰的代码。

第一个和第二个一样可读和可维护——如果你知道什么是代码> BION/CODE >。我使用Boost::Bind(本质上与std::tr1::Bind相同)的时间已经足够长了,所以我对它没有任何问题


<>一旦Tr1成为官方标准的一部分,你可以安全地假设任何有能力的C++程序员都会理解它。在此之前,它可能会带来一些困难,但我总是考虑长期而不是短期。

您忘记了
使用名称空间std::tr1::占位符

老实说,对于这样的简单算法,后一种代码可能更容易维护。但我实际上倾向于前者(特别是当C++1x给我们lambdas时!),因为它强调函数式编程风格,我个人更喜欢使用循环的命令式编程风格

这真的是另一回事;标准算法在复杂或通用时最有用,而这两者都不是

以下是lambdas的外观:

std::transform(m.begin(), m.end(), std::back_insterter(v),
               [](MyMap::value_type pair){ return pair.first; }
              );
事实上,还有另一种方法,我更喜欢它,但它太冗长了:

using std::tr1::bind;
using std::tr1::placeholders::_1;
std::for_each(m.begin(), m.end(),
              bind(&std::vector<int>::push_back, v,
                   bind(&MyMap::value_type::first, _1)
                  )
             );

选择选项1,参见Scott Meyers,43项,第181页。

当我昨天看你的问题时,迫使我看两遍以理解代码的不是绑定(我使用了很多),而是map::value\u type::first,我没有机会经常使用它。虽然我同意“清晰总是胜过聪明”,但在清晰之前需要熟悉,你不会熟悉你不使用的风格

我还想说,虽然选项2在理解预期用途方面更清晰,但它会更容易隐藏bug(选项1中的任何错误都更有可能在编译时可见)。

我选择选项3:

#包括
#包括
boost::push|u back(v,m | boost::adapters::map|u键);
其优点是:

  • 它比较短

  • 使用命名函数获取密钥

  • (可能)效率更高(因为
    boost::push_back
    可以调用
    reserve()
    on
    v

  • 并且不需要冗余的
    v.begin()
    v.end()


  • 任何其他方式都是纯粹的疯狂。

    我完全同意。很多人担心某些惯用代码的“可读性”,认为它可能不可读,但当你想到他们的目标读者是什么时,是那些对你正在编写的语言一无所知的人,但这个问题的全部要点是,我正试图在这一概念和第47项之间取得平衡(避免只写代码)。@Kristo,如果你真的对STL+TR1有一个亲密的、实践过的知识,那么选项1对你来说就像选项2一样可读。
    std::transform(m.begin(), m.end(), std::back_insterter(v),
                   [](MyMap::value_type pair){ return pair.first; }
                  );
    
    using std::tr1::bind;
    using std::tr1::placeholders::_1;
    std::for_each(m.begin(), m.end(),
                  bind(&std::vector<int>::push_back, v,
                       bind(&MyMap::value_type::first, _1)
                      )
                 );
    
    std::for_each(m.begin(), m.end(),
                  [&v](MyMap::value_type pair){v.push_back(pair.first);}
                 );
    
    #include <boost/range/adaptor/map.hpp>
    #include <boost/range/algorithm_ext/push_back.hpp>
    
    boost::push_back(v, m | boost::adaptors::map_keys);