GCC `__attribute__ ((pure))` 关于 "input state" getter 方法的建议 - 正确吗?
GCC `__attribute__ ((pure))` suggestion on "input state" getter method - correct?
使用 -Wsuggest-attribute=pure
编译使 GCC 建议可以使用 __attribute__ ((pure))
标记的潜在函数以进行优化。
这是 GCC 文档中的definition of pure
:
Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure.
我正在创建一个小型游戏引擎,其中有一个 input_context
class,其中包含一个 input_state
成员。 input_context
class 通过从操作系统获取全局输入状态来每帧更新 input_state
成员。
里面还有几个"getters"查询输入状态
简化示例:
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 methods",如 mouse_x()
、mouse_y()
和 is_key_down()
,都是 __attribute__ ((pure))
的候选者。
我应该将这些方法标记为 pure
吗?
我不这么认为,但是 GCC 的建议让我想知道。
我不确定如何解释 GCC 对 pure
的定义 - 它说 仅依赖参数 and/or 全局变量 的函数应该被标记为这样。
在某种程度上,全局 OS 输入状态可以解释为 全局变量。
另一方面,"getter methods"总是return不同的值,取决于_input_state
成员变量。
我认为您可以将这些方法标记为纯方法,因为它们没有副作用。
根据您引用的文档,纯函数可以依赖于全局 variable/external 状态。我猜这也和闭包的概念有关。您可以根据外部变量定义函数 f
(例如使用 Haskell):
x=1
f y = x + y
函数本身仍然没有副作用(尽管在 Haskell 中,您不能更改 x
的值,而您可以在 [=30] 之外更改 x
=] 在 C/C++).
pure
和const
的区别总结在这个问题中:
引用 :
attribute((const)) is the same as attribute((pure)) but without any access to global variables.
我认为将其标记为纯净是可以的。
以简化形式考虑您的示例,并添加了一些 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());
}
纯让你得到:
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
(系统更改 it/another 线程更改 it/a 信号处理程序更改它),编译器无法知道更改,那么 pure
属性不再合法。
使用 -Wsuggest-attribute=pure
编译使 GCC 建议可以使用 __attribute__ ((pure))
标记的潜在函数以进行优化。
这是 GCC 文档中的definition of pure
:
Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure.
我正在创建一个小型游戏引擎,其中有一个 input_context
class,其中包含一个 input_state
成员。 input_context
class 通过从操作系统获取全局输入状态来每帧更新 input_state
成员。
里面还有几个"getters"查询输入状态
简化示例:
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 methods",如 mouse_x()
、mouse_y()
和 is_key_down()
,都是 __attribute__ ((pure))
的候选者。
我应该将这些方法标记为 pure
吗?
我不这么认为,但是 GCC 的建议让我想知道。
我不确定如何解释 GCC 对 pure
的定义 - 它说 仅依赖参数 and/or 全局变量 的函数应该被标记为这样。
在某种程度上,全局 OS 输入状态可以解释为 全局变量。
另一方面,"getter methods"总是return不同的值,取决于
_input_state
成员变量。
我认为您可以将这些方法标记为纯方法,因为它们没有副作用。
根据您引用的文档,纯函数可以依赖于全局 variable/external 状态。我猜这也和闭包的概念有关。您可以根据外部变量定义函数 f
(例如使用 Haskell):
x=1
f y = x + y
函数本身仍然没有副作用(尽管在 Haskell 中,您不能更改 x
的值,而您可以在 [=30] 之外更改 x
=] 在 C/C++).
pure
和const
的区别总结在这个问题中:
引用
attribute((const)) is the same as attribute((pure)) but without any access to global variables.
我认为将其标记为纯净是可以的。 以简化形式考虑您的示例,并添加了一些 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());
}
纯让你得到:
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
(系统更改 it/another 线程更改 it/a 信号处理程序更改它),编译器无法知道更改,那么 pure
属性不再合法。