从c++函数中返回多个值的首选方法是什么?例如,假设有一个函数对两个整数进行除法并同时返回商和余数。我经常看到的一种方法是使用引用形参:

void divide(int dividend, int divisor, int& quotient, int& remainder);

一种变体是返回一个值,并通过引用形参传递另一个值:

int divide(int dividend, int divisor, int& remainder);

另一种方法是声明一个结构体来包含所有的结果并返回:

struct divide_result {
    int quotient;
    int remainder;
};

divide_result divide(int dividend, int divisor);

这些方法中是否有一种通常是首选的,还是有其他的建议?

编辑:在实际代码中,可能会有两个以上的结果。它们也可能是不同类型的。


当前回答

对于从一个函数返回多个值的通用系统,Boost tuple是我的首选。

可能的例子:

include "boost/tuple/tuple.hpp"

tuple <int,int> divide( int dividend,int divisor ) 

{
  return make_tuple(dividend / divisor,dividend % divisor )
}

其他回答

这完全取决于实际函数和多个值的含义,以及它们的大小:

如果它们像分数的例子一样相关,那么我会使用结构体或类实例。 如果它们不是真正相关的,并且不能被分组到一个类/结构中,那么也许你应该将你的方法重构为两个。 根据所返回值在内存中的大小,您可能希望返回指向类实例或结构的指针,或者使用引用形参。

我们可以这样声明函数,它返回一个用户定义的结构类型变量或指向它的指针。通过结构的属性,我们知道C语言中的结构可以保存多个不对称类型的值(即一个int变量,四个char变量,两个float变量等等)。

就我个人而言,我通常不喜欢返回参数,原因有很多:

在调用中,哪些参数是in,哪些是out并不总是很明显 您通常必须创建一个局部变量来捕获结果,而返回值可以内联使用(这可能是也可能不是一个好主意,但至少您可以选择) 对我来说,一个函数有一个“进”和一个“出”似乎更干净——所有的输入都在这里,所有的输出都在那里 我喜欢让我的论点列表尽可能简短

我对pair/tuple技术也有一些保留意见。主要是,返回值通常没有自然的顺序。代码的读者如何知道是否有结果。首先是商还是余数?实现者可以改变顺序,这将破坏现有的代码。如果值是相同的类型,因此不会生成编译器错误或警告,那么这种情况尤其危险。实际上,这些参数也适用于返回参数。

下面是另一个代码示例,这个示例不那么简单:

pair<double,double> calculateResultingVelocity(double windSpeed, double windAzimuth,
                                               double planeAirspeed, double planeCourse);

pair<double,double> result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.first << endl;
cout << result.second << endl;

这是打印地速和航向,还是航向和地速?这并不明显。

与此相比:

struct Velocity {
    double speed;
    double azimuth;
};
Velocity calculateResultingVelocity(double windSpeed, double windAzimuth,
                                    double planeAirspeed, double planeCourse);

Velocity result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.speed << endl;
cout << result.azimuth << endl;

我想这更清楚了。

所以我认为我的第一选择,一般来说,是结构技术。在某些情况下,对/元组思想可能是一个很好的解决方案。我希望尽可能避免返回参数。

在C(以及c++)标准中,有使用div、ldiv(以及C99中的lldiv)函数从<stdlib.h>(或<cstdlib>)返回结构的先例。

“返回值和返回参数的混合”通常是最不干净的。

让函数返回状态并通过返回参数返回数据在C中是合理的;在c++中,你可以使用异常来传递失败信息,这就不那么明显了。

如果有两个以上的返回值,那么类结构的机制可能是最好的。

OO解决方案是创建一个比率类。它不需要任何额外的代码(会节省一些代码),会明显更干净/清晰,并且会给你一些额外的重构,让你也可以清理这个类之外的代码。

实际上,我认为有人建议返回一个结构,这是足够接近,但隐藏的意图,这需要一个充分考虑的类与构造函数和一些方法,事实上,你最初提到的“方法”(作为返回对)应该最有可能是这个类的成员,返回自己的实例。

我知道你的例子只是一个“例子”,但事实是,除非你的函数做的比任何函数都要多,如果你想让它返回多个值,你几乎肯定会错过一个对象。

不要害怕创建这些小的类来做小的工作——这就是OO的神奇之处——你最终会分解它,直到每个方法都非常小而简单,每个类都非常小而可理解。

另一件事应该是一个错误的指示器:在OO中,你基本上没有数据——OO不是传递数据,一个类需要在内部管理和操作它自己的数据,任何数据传递(包括访问器)都是一个迹象,表明你可能需要重新考虑一些事情。