强制一个函数是纯函数

时间:2019-05-25 01:49:11

标签: c++

在C ++中,可以声明一个函数为const,据我所知,这意味着编译器确保该函数不会修改该对象。在C ++中,我可以要求函数是纯函数吗?如果不是使用C ++,是否有一种语言可以满足这一要求?

如果这不可能,为什么为什么可以要求函数为const但不要求它们为纯函数呢?这些要求有何不同?

为清楚起见,我只希望没有副作用,除了传递给函数的变量外,不要使用其他变量。因此,不应读取文件或进行系统调用等。

以下是对副作用的更清晰定义:

在运行该程序的计算机上没有对文件的修改,也没有对功能范围之外的变量进行修改。除了传递给函数的变量外,没有其他信息可用于计算函数。每次运行该函数都应返回相同的内容。

注意:我进行了更多研究,并遇到了pure script (感谢jarod42的评论)

基于对Wikipedia文章的快速阅读,我给您的印象是您可以要求函数必须使用纯脚本纯净,但是我不确定。

3 个答案:

答案 0 :(得分:1)

当前,C ++没有一种机制来确保函数“没有副作用,除了传递给函数的变量外,没有使用任何变量”。如Jack Bashford所述,您只能强迫自己编写纯函数。编译器无法为您进行检查。

有一个提案(N3744提案[[pure]])。在这里,您可以看到GCC和Clang已经支持__attribute__((pure))。也许它将在将来的C ++版本中以某种形式进行标准化。

答案 1 :(得分:0)

简短的回答:否。没有pure这样的等效关键字约束const一样的功能。

但是,如果您要保留一个特定的全局变量,则可以选择static type myVar。这将要求只有该文件中的函数才能使用它,而该文件之外的任何东西都不能使用。这意味着该文件外部的任何功能都将受到约束而无法保留。

关于“副作用”,我将分解每个副作用,以便您知道有哪些选择:

  • 不修改运行该程序的计算机上的文件。

您不能约束某个函数来执行此操作。 C ++只是没有提供约束这样的函数的方法。但是,您可以根据需要设计一个不修改任何文件的功能。

  • 不修改函数范围以外的变量。

除了指针或引用作为参数传递的任何内容外,全局变量是您可以在函数范围之外修改的唯一变量。全局变量可以选择为常量或静态变量,这将使您无法修改它们,但是除此之外,我知道您真的无能为力。

  • 除了传递给函数的变量外,没有其他信息可用于计算函数。

同样,您知道我不能限制它这样做。但是,您可以根据需要将功能设计为像这样工作。

  • 运行该函数应在每次运行时返回相同的内容。

我不确定我为什么要限制这样的功能,但是不知道。并不是我知道。同样,如果您愿意,也可以这样设计。

为什么C ++不提供这样的选项?我正在猜测可重用性。似乎您有一个特定的列表,这些列表是您不希望函数执行的操作。但是,作为一个整体,许多其他C ++用户将需要此特定约束集的可能性通常很小。也许他们一次只需要一两个,但不是一次全部需要。添加它似乎并不值得麻烦。

但是,关于const不能说相同。 const一直使用,尤其是在参数列表中。如果通过引用或其他方式传递数据,这将防止数据被修改。因此,编译器需要知道哪些函数会修改对象。它在函数声明中使用const进行跟踪。否则,它将无法得知。但是,使用const非常简单。它可以限制对象只使用保证其保持不变的函数,或者在函数中的声明中使用const关键字。

因此,const得到了很多重用。

答案 2 :(得分:0)

  

在C ++中,可以声明一个函数为const,据我所知,这意味着编译器确保该函数不会修改该对象。

不完全是。编译器将允许使用const_cast来修改对象(可能不建议使用)。因此,编译器仅确保函数不会意外修改对象。

  

是什么使这些要求(恒定和纯粹)不同?

它们是不同的,因为一个影响正确的功能,而另一个不影响正确的功能。

假设C是一个容器,并且您要遍历其内容。在循环内的某个时刻,也许您需要调用一个以C作为参数的函数。如果该功能用于clear()容器,则循环可能会崩溃。当然,您可以构建一个可以处理该问题的循环,但要点是,有时呼叫者需要确保不会将地毯从其下面拉出。因此,可以标记事物const。如果将C作为对函数的常量引用进行传递,则该函数有望不修改C。该承诺提供了必要的保证(即使如上所述,该承诺也可能被破坏)。

我不知道使用非纯函数会类似地导致程序崩溃的情况。如果没有用处,为什么还要使语言复杂化?如果您能提出一个很好的用例,则可能是将来对该语言进行修订的考虑因素。

(知道函数是纯函数可以帮助编译器优化代码。据我所知,它由每个编译器来定义如何标记它,因为它不会影响功能。)