繁体   English   中英

如果没有if,std :: count_if会更快吗?

[英]Would std::count_if be faster without an if?

这是gcc std::count_if代码

template<typename _InputIterator, typename _Predicate>
  typename iterator_traits<_InputIterator>::difference_type
  count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
 {
  [snip]
  typename iterator_traits<_InputIterator>::difference_type __n = 0;
  for (; __first != __last; ++__first)
    if (__pred(*__first))
      ++__n;
  return __n;
}

我的问题:使用它会更好(即更快)

__n += __pred(*__first); // instead of the if statement

此版本始终执行添加,但不执行分支。

您提供的替换等同,因为对谓词的限制远远少于您的想法:

  • 可以在条件上下文中使用的任何内容(可以在上下文中转换为bool )是谓词的有效返回类型( explicit转换为bool就足够了)。
  • 返回类型可以很有趣地添加到迭代器差异类型。

25算法库[algorithms]

25.1一般[algorithms.general]

8 Predicate参数用于每当算法期望的功能对象(20.9),当施加到解引用相应的迭代的结果,返回可测试作为值true 换句话说,如果算法将Predicate pred作为其参数并first作为其迭代器参数,则它应该在构造pred(*first)上下文中正确转换为bool (第4条) 函数对象pred不应通过解引用的迭代器应用任何非常量函数。

给予替代消化不良的最可能的回报是标准整数类型,并且值既不是0也不是1。

另外,请记住编译器现在实际上可以真正优化(特别是C ++需要,所有模板 - 东西分层深)。

所以,首先,您建议的代码是不同的。 那么让我们看看两个等价的代码:

template<typename _InputIterator, typename _Predicate>
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
    typename iterator_traits<_InputIterator>::difference_type __n = 0;
    for (; __first != __last; ++__first)
        if (__pred(*__first))
            ++__n;
    return __n;
}

和:

template<typename _InputIterator, typename _Predicate>
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
    typename iterator_traits<_InputIterator>::difference_type __n = 0;
    for (; __first != __last; ++__first)
        __n += (bool) __pred(*__first);
    return __n;
}

然后,我们可以使用编译器编译它并查看程序集。 在我尝试过的一个编译器(os x on clax)下,这些编译器产生了相同的代码

也许你的编译器也会产生相同的代码,或者它可能产生不同的代码。

从技术上讲,它会,但请记住,所有大于0值都会评估为true 因此被调用的函数可能会返回一个不是1的值,这会使结果产生偏差。 此外,编译器还具有将分支优化为条件移动的方法。

为了扩展,有一些方法可以在代码中优化分支,但这会降低可读性和可维护性,以及通过例如调试代码的能力。 把断点放下来,并且获得很少,因为编译器非常善于自己优化这些东西。

由编译器生成的代码不必在字面上机器代码重现C ++语言构造。 仅仅因为您的C ++代码中包含if语句并不意味着机器代码将基于分支指令。 现代编译器不需要也不要在生成的机器代码中实现抽象C ++机器的行为。

因此,不可能说它是否会更快。 C ++代码没有任何与之相关的固有“速度”。 C ++代码永远不会直接执行。 从抽象的角度来看,它不能“更快”或“更慢”。 如果要通过查看代码来分析代码的性能,则必须查看编译器生成的机器代码,而不是C ++代码。 但是更好的方法是尝试两种变体并通过在各种典型输入数据上实际运行它们来对它们进行分析。

智能编译器很可能会为您的两个变体生成相同的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM