返回值和副作用编码之间有什么区别

What are the differences between returning values and side effect coding?

本文关键字:什么 区别 之间 编码 副作用 返回值      更新时间:2023-10-16

我的问题是由一个C++代码引起的,这个代码不是我的,我目前正在努力理解。尽管如此,我认为OO开发人员通常可以回答这个问题(因为我在Java代码中见过这种情况)。

通过阅读代码,我注意到开发人员总是使用副作用(除了getter和一些罕见的情况外,大多数函数都具有"void返回类型"),而不是直接返回结果。他有时使用返回值,但仅用于控制流(错误代码…而不是异常)。

以下是他的原型的两个可能的例子(伪代码):对于应返回矩阵M中浮点值的最小值、最大值和平均值的函数:

void computeStatistics(float min, float max, float avg, Matrix M);

void computeStatistics(List myStat, Matrix M);

对于一个函数,它应该返回给定列表中的一些对象,该列表验证特定的标准和找到的对象数量:

int controlValue findObjects(List result, int nbObjectsFound, Object myCriteria, List givenList)

我不熟悉C++,你可能会在我的伪代码中看到。。。但在Matlab中,可以从函数中同时返回所需的一切,例如int和List(这对第二个示例可能很有用)。我知道这在C++中是不可能的,这可以解释第二个原型,但它不能解释他本可以做的第一个例子的选择:

List myStat computeStat(Matrix M)

最后,我的问题是:有哪些可能的原因可以激励这种选择?这是一种良好的做法,一种惯例,还是仅仅是一种发展选择?一种方法比另一种方法有优势吗(返回值与副作用方法)?

在C++方面:

IMO使用返回值比通过引用传递值更清楚,并且在大多数情况下没有开销。(请查看RVO和Copy Elision)

然而,如果您确实为控制流使用了返回值,那么使用引用并不是一件坏事,对大多数开发人员来说仍然很清楚。

所以我想我们可以说选择权在你。

还要记住,许多开发人员不知道C++编译器在做什么魔术,因此使用返回值可能会冒犯他们。

在过去,使用引用参数作为输出是一种常见的做法,因为如果没有返回值优化(移动语义),返回复杂对象的速度非常慢。今天,我相信在大多数情况下,返回值是最好的选择。

想要速度?传递值。

在列表有副本的情况下编写以下内容被我认为是不合适的。

void computeStatistics(List myStat, Matrix M);

相反(只要该列表有副本),你应该这样做。

List myStat computeStat(Matrix M)

然而,如果你的对象上没有副本,那么你就不需要在堆上分配它,而是可以在堆栈上分配它并向你的函数发送一个指向它的指针

关于:

void computeStatistics(float min, float max, float avg, Matrix M);

我个人的观点是,最佳实践是一种方法,一个目的,所以我会这样做:

float min computeMin(Matrix M);
float max computeMax(Matrix M);
float avg computeAvg(Matrix M);

我能看到在一个函数中完成所有这些的唯一原因是,计算不是单独完成的(在单独的函数中做更多的工作)。

然而,如果您需要在一个方法中有多个返回类型,我会通过引用调用来实现。例如:

void SomeMethod(input1, input2, &output1, &output2, &output3)