2

编译-Wsuggest-attribute=pure使 GCC 建议潜在的函数,这些函数可以标记__attribute__ ((pure))为优化目的。

这是GCC 文档上的定义:pure

许多函数除了返回值外没有任何影响,它们的返回值仅取决于参数和/或全局变量。这样的函数可以像算术运算符一样进行公共子表达式消除和循环优化。这些函数应该用纯属性声明。

我正在创建一个小型游戏引擎,其中有一个input_context包含input_state成员的类。该类通过从操作系统获取全局输入状态来input_context更新每个帧的成员。input_state

它还包含几个“getter”来查询输入状态。

简化示例:

class input_context
{
private:
    input_state _input_state;

public:
    void update()
    {
        os::fill_input_state(_input_state);
    }

    auto mouse_x() const noexcept
    { 
        return _input_state._mouse_x;
    }

    auto mouse_y() const noexcept
    { 
        return _input_state._mouse_y;
    }

    auto is_key_down(keycode k) const noexcept
    { 
        // `_keys` is an array of `bool` values.
        return _input_state._keys[k];
    }
};

GCC 告诉我所有这些“getter 方法”,比如和mouse_x(),都是.mouse_y()is_key_down()__attribute__ ((pure))

我应该将这些方法标记为pure吗?

我不这么认为,但 GCC 的建议让我对此感到好奇。

我不确定如何解释 GCC 的定义pure——它说只依赖参数和/或全局变量的函数应该被标记为这样。

  • 在某种程度上,全局 OS 输入状态可以解释为全局变量

  • 另一方面,“getter 方法”总是返回不同的值,具体取决于_input_state成员变量。

4

2 回答 2

1

我认为您可以将这些方法标记为纯方法,因为它们没有副作用。

根据您引用的文档,纯函数可以依赖于全局变量/外部状态。我想这也与闭包的概念有关。f您可以基于外部变量定义一个函数(例如使用 Haskell):

x=1
f y = x + y

函数本身仍然没有副作用(尽管在 Haskell 中,您无法更改 的值x,而您可以x在 C/C++ 中的函数/方法之外进行更改)。

pure和之间的区别const总结在这个问题:__attribute__((const)) vs __attribute__((pure)) in GNU C

引用那里的答案

属性((const)) 与属性((pure)) 相同,但不能访问全局变量。

于 2016-02-01T17:51:15.747 回答
1

我相信将其标记为纯是可以的。以简化的形式考虑您的示例,并添加了一些 IO 功能:

#include <stdio.h>
class X {
  int x_=0;
public:
  int x() const noexcept __attribute__ ((pure)) /*__attribute__((noinline))*/;
  void inc() noxcept { x_++; }
};
int X::x() const noexcept { puts("getting x"); return x_;}
int main(){
  X x;
  printf("%d\n", x.x() + x.x() + x.x());
  x.inc();
  printf("%d\n", x.x() + x.x() + x.x());
}

pure让您获得:

getting x
0
getting x
3

代替

getting x
getting x
getting x
0
getting x
getting x
getting x
3

在优化级别至少 -O1 (在更高级别,您可能需要添加__attribute__((noinline))以防止内联)。

只要编译器可以检测到状态发生了变化,如果状态在两次连续调用这些 getter 之间发生变化是可以的。如果您需要运行一种non-const方法来更改状态,那么这不会违反纯度。但是,如果状态on its own以编译器无法知道的方式更改(系统更改/另一个线程更改/信号处理程序更改),则该pure属性不再合法。

于 2016-02-01T18:23:38.857 回答