GNU常量/纯属性与常量表达式 GNU C和C++提供了 const 和纯< /Cord>函数属性。 从(我的)重点: 在GNU C和C++中,可以使用函数属性指定某些函数属性,这些属性可以帮助编译器优化调用或更仔细地检查代码以确保正确性。例如,可以使用属性指定函数从不返回(noreturn),仅根据其参数值(const)返回值,或者具有printf样式的参数(format)
其中const属性似乎是pure的超集,也取自: const属性对函数的 定义比纯属性相似。声明相同 诊断同时具有常量和纯属性的函数 < + > C++ 11,加入。 当应用于函数时,const属性和constexpr说明符之间是否存在差异?GCC是否应用了不同的优化 一个听起来类似的问题是。但我认为这不是复制品。我的问题是关于函数属性GNU常量/纯属性与常量表达式 GNU C和C++提供了 const 和纯< /Cord>函数属性。 从(我的)重点: 在GNU C和C++中,可以使用函数属性指定某些函数属性,这些属性可以帮助编译器优化调用或更仔细地检查代码以确保正确性。例如,可以使用属性指定函数从不返回(noreturn),仅根据其参数值(const)返回值,或者具有printf样式的参数(format),c++,c,gcc,constexpr,purely-functional,C++,C,Gcc,Constexpr,Purely Functional,其中const属性似乎是pure的超集,也取自: const属性对函数的 定义比纯属性相似。声明相同 诊断同时具有常量和纯属性的函数 < + > C++ 11,加入。 当应用于函数时,const属性和constexpr说明符之间是否存在差异?GCC是否应用了不同的优化 一个听起来类似的问题是。但我认为这不是复制品。我的问题是关于函数属性const,它似乎与constepr有重叠的功能 当应用于函数时,const属性和constexpr说明符之间是否存在差异 这是有区别的 首先,C没有conste
const
,它似乎与constepr
有重叠的功能
当应用于函数时,const属性和constexpr说明符之间是否存在差异
这是有区别的
首先,C没有constexpr,所以在该语言中不能利用它
对constexpr函数的调用可以是常量表达式。因此,它们的结果可以用作数组的大小。GNU属性不能用于实现相同的功能(忽略GCC VLA语言扩展)
Constexpr函数有利于在编译时利用预计算。GNU属性在允许编译器利用运行时常量方面仍然很有用。例如,假设有一个函数不能是constexpr——可能是因为它调用了一个非constexpr函数。但我们可能知道,对函数的每次调用都会产生相同的输出,并且没有副作用。Const属性允许编译器不重复冗余调用
另一个区别是constexpr函数必须内联定义。非constexpr函数不需要内联定义。另一个区别是,
\uuuuu attribute\uuuu((const))
函数必须为同一个参数返回相同的输出值(如果我没有错的话;这是我第一次看到这个属性;)。不需要为constexpr
函数保留该值
一个学术例子:
constexpr int rand(int n)
{
std::string_view sv(时间);
返回sv.back()%n;
}
std::数组a;//示范用法
虽然
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
):
这会写入内存,gnu::pure
函数无法做到这一点
constexpr
只是意味着可以在编译时调用它。这与gnu::const
和gnu::pure
有重叠,因为您不能写入全局变量或访问易失性内存(从C++的角度来看,所有IO操作都访问易失性内存),但它们都有其他限制,使它们不同
在C++11中,constexpr
的限制要大得多。您无法写入任何引用参数,因此我认为C++11constexpr
是gnu::pure
的严格子集。下面是一个C++11 constexpr函数的示例,该函数不能标记为gnu::const
:
[[gnu::pure]] constexpr int f(int const & x) {
return x;
}
是的,更好的标题:)
时间是一个预处理器宏。它将在编译函数时展开,这意味着每个调用将返回相同的值。如果在标题中定义此函数并从多个翻译单元(源文件)中包含它,则将违反“一个定义规则”(“ODR”),因为有两个函数具有不同的主体,但具有相同的名称和签名,这意味着程序未定义。
constexpr void f(int & x) {
x = 1;
}
[[gnu::pure]] constexpr int f(int const & x) {
return x;
}