C ++ 11中的纯函数

时间:2012-12-02 22:46:07

标签: c++ gcc c++11

可以在gcc中以某种方式在C ++ 11中将一个函数(不是类方法)标记为const,告诉它并且不使用全局记忆但只有它的论点?

我已经尝试了gcc的{​​{1}},而且正是我想要的东西。但是当在函数中触摸全局内存时,它不会产生任何编译时错误。

修改1

请小心。我是指纯粹的功能。 非常数函数。 GCC的属性有点令人困惑。纯函数只使用它们的参数。

3 个答案:

答案 0 :(得分:7)

您在寻找constexpr吗?这告诉编译器可以在编译时评估该函数。 constexpr函数必须具有文字返回和参数类型,并且正文只能包含静态断言,typedef,使用声明和指令以及一个return语句。可以在常量表达式中调用constexpr函数。

constexpr int add(int a, int b) { return a + b; }

int x[add(3, 6)];

看了__atribute__((const))的含义,答案是否定的,你不能用标准的C ++做到这一点。使用constexpr将获得相同的效果,但仅限于更有限的一组功能。然而,只要编译的程序行为相同(as-if规则),就没有什么能阻止编译器自己进行这些优化。

答案 1 :(得分:2)

因为这里已经提到了很多,让我们暂时忘记Meta编程,这无论如何都是纯粹的功能和主题。 但是,可以使用非constexpr参数调用constexpr函数 foo ,在此上下文中, foo 实际上是在运行时评估的纯函数。但是你可以写许多你不能做constexpr的纯函数,这包括抛出例外的任何函数。

其次我假设OP意味着标记纯作为编译器要检查的断言。 GCC的属性是相反的,是编码器帮助编译器的一种方式。

虽然OP的问题的答案是否定的,但是阅读有关尝试引入纯关键字的历史(或不纯的并让纯<< / em>是默认值。

d-lang社区很快发现了&#34; pure&#34;不清楚。记录不应该使函数不纯。在纯函数中应该允许不转义函数调用的可变变量。具有不同地址的等回报值不应被视为不纯。但D比拉伸纯度更进一步。

因此,d-lang社区引入了“弱纯度”一词。并且&#34;非常纯粹&#34;。但后来的争议表明,弱者和强者并非黑白,而且还有灰色地带。见purity in D

Rust介绍了&#34; pure&#34;关键词早期;由于其复杂性,他们放弃了它。见purity in Rust

纯粹的&#34;纯粹的&#34;关键字虽然有一个丑陋的后果。模板化函数可以是纯函数还是不纯函数,具体取决于其类型参数。这可能会爆炸模板实例化的数量。这些实例化可能只需要在编译器中暂时存在,而不是进入可执行文件,但它们仍然可能会爆炸编译时间。

语法高亮编辑器可以在不修改语言的情况下提供一些帮助。优化C ++编译器确实可以推断出函数的纯粹性,它们并不能保证能够捕获所有情况。

我觉得很遗憾这个功能似乎优先级低。它使代码的推理变得如此简单。我甚至认为它会通过激励程序员以不同的方式思考来改进软件设计。

答案 2 :(得分:0)

仅使用标准C ++ 11:

namespace g{ int x; }

constexpr int foo()
{
    //return g::x = 42;  Nah, not constant
    return 42;      // OK
}

int main()
{}

这是另一个例子:

constexpr int foo( int blah = 0 )
{
    return blah + 42;      // OK
}

int main( int argc, char** )
{
    int bah[foo(2)];            // Very constant.
    int const troll = foo( argc );  // Very non-constant.
}

GCC __attribute__( const )的含义记录在GNU compiler docs中......

  

除了参数之外,许多函数不检查任何值,除了返回值之外没有任何效果。基本上这只是比下面的pure属性稍微严格的类,因为不允许函数读取全局内存。

有人可能会认为函数结果只取决于参数,并且函数应该没有副作用。

这允许比C ++ 11 constexpr更通用的一类函数,它使函数inline将参数和函数结果限制为文字类型,并限制函数体的“活动”语句到单个return语句,其中(C ++11§7.1.5/ 3)

  

- 初始化返回值(6.6.3,8.5)时使用的每个构造函数调用和隐式转换都应该是常量表达式中允许的一个(5.19)

作为一个例子,制作constexpr sin函数很困难(我认为并非不可能,但很难)。

但结果的纯度只对双方有关:

  • 当知道纯粹时,编译器可以忽略具有已知结果的调用 这主要是宏生成代码的优化。将宏替换为inline函数,以避免生成相同的子表达式。

  • 当知道纯粹时,程序员可以完全删除一个电话 这只是正确的文档的问题。 : - )

因此,而不是寻找一种表达纯度的方法,而不是在语言sin中,我建议只是避免通过宏生成代码,并将纯函数记录下来。

并将constexpr用于实际可能的函数(不幸的是,截至2012年12月,最新的Visual C ++编译器尚不支持constexpr)。


之前有一个关于the relationship between pure and constexpr的SO问题。主要是,每个constexpr函数都是,但反之亦然。