GNU const/pure 属性与 constexpr
GNU const/pure attributes vs constexpr
GNU C 和 C++ 提供 const
和 pure
函数属性。
来自 gnu online docs(强调我的):
在 GNU C 和 C++ 中,您可以使用函数属性来指定某些函数属性,这些属性可能有助于编译器优化调用或更仔细地检查代码的正确性。例如,您可以使用属性来指定函数永远不会 returns (noreturn),returns 值仅取决于其参数的值 (const) ,或具有 printf 样式的参数(格式)。
其中 const 属性似乎是 pure 的子集,也取自 gnu docs:
The const attribute imposes greater restrictions on a function’s
definition than the similar pure attribute. Declaring the same
function with both the const and the pure attribute is diagnosed.
在 C++ 11 中,添加了 constexpr
specifier。
应用于函数时,const 属性和 constexpr 说明符之间有区别吗? GCC 是否应用不同的优化?
一个类似的问题是 Difference between `constexpr` and `const`。但我认为这不是重复的。我的问题具体是关于函数属性 const
,它似乎与 constexpr
.
有重叠的功能
When applied to functions, is there a difference between the const attribute and the constexpr specifier?
有区别。
首先,C 没有 constexpr,因此您无法在该语言中利用它。
constexpr 函数的调用可以是常量表达式。因此,它们的结果可以用作例如数组的大小。 GNU 属性不能用于实现相同的目的(忽略 GCC VLA 语言扩展)。
Constexpr 函数有利于在编译时利用预计算。 GNU 属性对于允许编译器利用运行时常量性仍然很有用。例如,假设有一个函数不能是 constexpr - 可能是因为它调用了一个非 constexpr 函数。但我们可能知道每次调用该函数都会产生相同的输出而没有副作用。 Const属性允许编译器不重复冗余调用。
另一个区别是 constexpr 函数必须内联定义。不需要内联定义非 constexpr 函数。
另一个区别是 __attribute__ ((const))
函数必须 return 相同参数的相同输出值 (如果我没记错的话;这是我第一次看到这个属性;)。这不需要为 constexpr
函数成立。
一个学术例子:
constexpr int rand(int n)
{
std::string_view sv(__TIME__);
return sv.back() % n;
}
std::array<int, rand(10) + 1> a; // exemplary usage
虽然 rand
是 constexpr
,但对于相同的输入参数,它可能会产生不同的输出。
它们之间几乎没有重叠。这是一个 gnu::const
(因此 gnu::pure
)但不能是 constexpr
:
的函数
[[gnu::const]] int f() {
struct s {
int m;
};
union {
s a;
s b;
};
a.m = 1;
return b.m;
}
您无法读取常量表达式中联合的公共初始子序列,因此此函数永远不会生成常量表达式。
下面是一个constexpr
但不能是gnu::pure
的函数(因此不能是gnu::const
):
constexpr void f(int & x) {
x = 1;
}
这会写入内存,这是 gnu::pure
函数无法做到的。
constexpr
只是表示可以在编译时调用。这与 gnu::const
和 gnu::pure
重叠,因为您不能写入全局变量或访问易失性内存(从 C++ 的角度来看,所有 IO 操作都访问易失性内存),但它们各自有其他限制使它们截然不同。
在 C++11 中,constexpr
受到更多限制。您不能写入任何引用参数,所以我认为 C++11 constexpr
是 gnu::pure
的严格子集。下面是一个C++11 constexpr函数的例子,不能标记为gnu::const
,然而:
[[gnu::pure]] constexpr int f(int const & x) {
return x;
}
GNU C 和 C++ 提供 const
和 pure
函数属性。
来自 gnu online docs(强调我的):
在 GNU C 和 C++ 中,您可以使用函数属性来指定某些函数属性,这些属性可能有助于编译器优化调用或更仔细地检查代码的正确性。例如,您可以使用属性来指定函数永远不会 returns (noreturn),returns 值仅取决于其参数的值 (const) ,或具有 printf 样式的参数(格式)。
其中 const 属性似乎是 pure 的子集,也取自 gnu docs:
The const attribute imposes greater restrictions on a function’s definition than the similar pure attribute. Declaring the same function with both the const and the pure attribute is diagnosed.
在 C++ 11 中,添加了 constexpr
specifier。
应用于函数时,const 属性和 constexpr 说明符之间有区别吗? GCC 是否应用不同的优化?
一个类似的问题是 Difference between `constexpr` and `const`。但我认为这不是重复的。我的问题具体是关于函数属性 const
,它似乎与 constexpr
.
When applied to functions, is there a difference between the const attribute and the constexpr specifier?
有区别。
首先,C 没有 constexpr,因此您无法在该语言中利用它。
constexpr 函数的调用可以是常量表达式。因此,它们的结果可以用作例如数组的大小。 GNU 属性不能用于实现相同的目的(忽略 GCC VLA 语言扩展)。
Constexpr 函数有利于在编译时利用预计算。 GNU 属性对于允许编译器利用运行时常量性仍然很有用。例如,假设有一个函数不能是 constexpr - 可能是因为它调用了一个非 constexpr 函数。但我们可能知道每次调用该函数都会产生相同的输出而没有副作用。 Const属性允许编译器不重复冗余调用。
另一个区别是 constexpr 函数必须内联定义。不需要内联定义非 constexpr 函数。
另一个区别是 __attribute__ ((const))
函数必须 return 相同参数的相同输出值 (如果我没记错的话;这是我第一次看到这个属性;)。这不需要为 constexpr
函数成立。
一个学术例子:
constexpr int rand(int n)
{
std::string_view sv(__TIME__);
return sv.back() % n;
}
std::array<int, rand(10) + 1> a; // exemplary usage
虽然 rand
是 constexpr
,但对于相同的输入参数,它可能会产生不同的输出。
它们之间几乎没有重叠。这是一个 gnu::const
(因此 gnu::pure
)但不能是 constexpr
:
[[gnu::const]] int f() {
struct s {
int m;
};
union {
s a;
s b;
};
a.m = 1;
return b.m;
}
您无法读取常量表达式中联合的公共初始子序列,因此此函数永远不会生成常量表达式。
下面是一个constexpr
但不能是gnu::pure
的函数(因此不能是gnu::const
):
constexpr void f(int & x) {
x = 1;
}
这会写入内存,这是 gnu::pure
函数无法做到的。
constexpr
只是表示可以在编译时调用。这与 gnu::const
和 gnu::pure
重叠,因为您不能写入全局变量或访问易失性内存(从 C++ 的角度来看,所有 IO 操作都访问易失性内存),但它们各自有其他限制使它们截然不同。
在 C++11 中,constexpr
受到更多限制。您不能写入任何引用参数,所以我认为 C++11 constexpr
是 gnu::pure
的严格子集。下面是一个C++11 constexpr函数的例子,不能标记为gnu::const
,然而:
[[gnu::pure]] constexpr int f(int const & x) {
return x;
}