GNU const/pure 属性与 constexpr

GNU const/pure attributes vs constexpr

GNU C 和 C++ 提供 constpure 函数属性。 来自 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

虽然 randconstexpr,但对于相同的输入参数,它可能会产生不同的输出。

它们之间几乎没有重叠。这是一个 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::constgnu::pure 重叠,因为您不能写入全局变量或访问易失性内存(从 C++ 的角度来看,所有 IO 操作都访问易失性内存),但它们各自有其他限制使它们截然不同。

在 C++11 中,constexpr 受到更多限制。您不能写入任何引用参数,所以我认为 C++11 constexprgnu::pure 的严格子集。下面是一个C++11 constexpr函数的例子,不能标记为gnu::const,然而:

[[gnu::pure]] constexpr int f(int const & x) {
    return x;
}