为什么功能过程的规律性允许按值传递和按常量引用传递?

Why does the regularity of functional procedures allow passing by value & passing by constant reference?

在 Alexander A. Stepanov 和 Paul McJones 的编程基础一书中指出:

The regularity of functional procedures allows two techniques for passing inputs. When the size of the parameter is small or if the procedure needs a copy it can mutate, we pass it by value, making a local copy. Otherwise we pass it by constant reference.

使用书中的以下定义

A procedure is regular if and only if replacing its inputs with equal objects results in equal output objects.

假设存在一个对象类型,用一个词表示布尔值,我们称它为foolean。 0 被解释为假,所有其他状态 (1...n) 被解释为真。

现在让我们假设存在一个过程,它采用一个 foolean 值,return将其表示为零和一的字符串。

这个过程显然不规则,因为可以向它传递许多真值,并且它会 return 不同的输出对象。但是,我看不出按值或常量引用将输入传递给它会有什么问题(除了这样的数据类型一开始是不明智的!)。

与允许这两种技术的其他程序相比,功能程序的规律性如何?

一个属性常规类型是:

auto a = b;
assert(a==b);

成立;份数相等。你可以有一个 没有 的不规则类型 属性;例如,== 可能会检查身份,而副本可能会创建一个单独的身份。

在常规程序中,我们有 属性 如果 (a==b),则 f(a)f(b) 具有相同的效果。

但是f( X const& )不复制,而f( X )复制。因此,如果类型 X 不规则,因为副本不相等,则将 f( X const& ) 转换为 f( X ) 可以改变行为。

现在你不需要完全的规律性来保持这个,但是这个 属性 是由函数和类型的规律性暗示的。

我觉得重要的是:

The regularity of functional procedures allows two techniques for passing inputs. When the size of the parameter is small or if the procedure needs a copy it can mutate, we pass it by value, making a local copy. Otherwise we pass it by constant reference.

对于 C++ 中的任何函数,这实际上都是一个很好的做法。

按值传递对象会在内存中创建一个副本,因此如果对象很大并且您真的不需要可变副本,您真的不想这样做,那是您通过引用传递它的时候(不会创建副本)。请注意,除非您确实需要可变引用(您不应该这样做),否则您应该始终更喜欢传递 const 引用。

常规函数只是向您保证,当您创建一个副本时,您不会改变行为。

此外,您在那里描述的函数(带有 foolean 常规函数。规律性并不意味着没有两个输入可以产生相同的输出。 f(1) == f(2) 并不意味着 f 不规则,只要 f(1) 仍然与 f(copy(1)) 相同(有时不是)。