C++ 23 静态运算符()的效率优势

问题描述 投票:0回答:1

我正在研究本文中阐述的静态运算符()的动机

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1169r2.html

他们解释说,STL 算法中经常使用的函数对象会产生将其 this 指针存储在寄存器中的额外成本,即使operator() 不使用它。

为此他们给出了以下代码示例: https://godbolt.org/z/ajTZo2

运行算法以使用函数对象的静态函数而不是非静态运算符()确实会产生更短的汇编代码。 (他们使用 -DSTATIC 运行一次,不使用 -DSTATIC 运行一次)

struct X {
    bool operator()(int) const;
    static bool f(int);
};

inline constexpr X x;

int count_x(std::vector<int> const& xs) {
    return std::count_if(xs.begin(), xs.end(),
#ifdef STATIC
    X::f
#else
    x
#endif
    );
}   

但是,当我更改函数以实际执行某些操作时,无论是仅返回 true,还是将参数与硬编码值进行比较,差异似乎消失了,并且生成的程序集似乎是相同的,让我仍在搜索为了利用静态运算符()的优势。

#include <vector>
#include <algorithm>
using namespace std;

struct X {
    bool operator()(int data ) { return data > 5; } ;
    static bool f(int data) { return data > 5; } ;
};

inline constexpr X x;

int count_x(std::vector<int> const& xs) {
    return std::count_if(xs.begin(), xs.end(),
#ifdef STATIC
    X::f
#else
    x
#endif
    );
}

谁能解释一下吗?

编辑: 顺便说一句,将代码更改为以下内容,返回汇编差异

struct X {
    bool operator()(int data ) ;
    static bool f(int data);
};

 __attribute__ ((noinline))  bool X::operator() (int data) {
     { return data > 5; } 
}

 __attribute__ ((noinline)) bool X::f(int data )
     { return data > 5; } 

inline constexpr X x;

int count_x(std::vector<int> const& xs) {
    return std::count_if(xs.begin(), xs.end(),
#ifdef STATIC
    X::f
#else
    x
#endif
    );
}
c++ static-methods functor c++23
1个回答
4
投票

如果函数被内联,那么当然实际的调用约定是什么并不重要——它被内联了。但是该函数不会内联,那么您必须发出对该函数的调用 - 这最终会做不必要的工作。

这基本上就是能够将调用运算符注释为

static
的要点。如果不需要对象参数,只需从签名中明确表示不需要对象参数即可。您已经可以在命名函数上执行此操作,只是如果您的成员函数碰巧被命名为
()
,则无法执行此操作。这是一种武断的限制,使您无法清楚地表达您的意图。

此外,它使编译器的工作变得更容易——如果一开始就没有对象参数,则不必优化对象参数。内联失败是一种致命的千刀万剐的考验,所以每一点都有帮助。

(来源:这是我的建议)

© www.soinside.com 2019 - 2024. All rights reserved.