pragma Pure
您应该在任何没有内部状态的包上使用它。它告诉包的用户调用任何子程序都不会产生副作用,因为它们没有可以改变的内部状态。因此,在纯包内的库级别声明的函数在使用相同参数调用时将始终返回相同的结果。
Ada 实现允许缓存纯包的函数的返回值,如果由于这些要求而不会使用子程序的返回值,则可以省略对子程序的调用。但是,您可以通过在纯包中调用导入的子例程(例如,从 C 库中)来违反约束(这些可能会更改 Ada 编译器不知道的某些内部状态)。如果你是邪恶的,你甚至可以从软件的其他部分导入 Ada 子程序pragma Import
来绕过pragma Pure
. 不用说:如果你正在做这样的事情,不要使用pragma Pure
.
编辑:为了澄清可以省略调用的情况,让我引用ARM:
如果一个库单元被声明为纯的,那么如果在调用之后不需要结果,则允许实现省略对该库单元的库级子程序的调用。类似地,它可以省略这样的调用,并简单地重用先前对同一子程序的调用产生的结果,前提是没有一个参数是有限类型的,并且所有通过引用的实际参数的地址和值,以及所有 by-copy-in 实际参数的值与之前调用时的值相同。即使子程序在调用时产生其他副作用,此权限也适用。
例如,GNAT 还定义了任何采用类型参数System.Address
或派生自它的类型的子程序都不会被视为纯程序,即使它们是在纯程序包中定义的,因为地址指向的位置可能会改变,但 GNAT 会不知道地址指向哪种结构,因此无法检查参数的引用值是否已更改。
pragma Preelaborate
这告诉编译器包不会在精化时执行任何代码(即在主过程开始执行之前)。在细化时,将执行以下构造:
- 初始化库级变量(这可以是函数调用)
- 在库级别声明的任务的初始化(它们可能在主过程之前开始执行)
begin ... end
库级别的块中的语句
如果你不需要它们,你通常应该避免这些东西。pragma Preelaborate
尽可能使用,它告诉调用者他可以安全地使用包,而无需在细化时执行任何操作。
如果在您认为应该使用这些 pragma 之一编译某些东西时,请查看它为什么无法编译。它可以帮助您发现包实现或结构的问题。不要在编译不了的时候放弃编译指示。由于约束会影响依赖于您的任何包的可能约束,因此您应该始终选择最严格的适用编译指示。