返回值和副作用编码之间有什么区别
What are the differences between returning values and side effect coding?
我的问题是由一个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)
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- typedef 枚举和枚举类有什么区别?
- &C::c 和 &(C::c) 有什么区别?
- ascii 和 unicode 在处理级别有什么区别吗?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- "ABC" 和 "ABC" ) 在C++中有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 这两种C++语法之间有什么区别?
- lua 5.0.2 模块和 5.3.5 有什么区别?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- std::enable_if 和 std::enable_if_t 有什么区别?