从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);

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

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


当前回答

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

在调用中,哪些参数是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;

我想这更清楚了。

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

其他回答

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

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

std::pair<int, int> divide(int dividend, int divisor)
{
   // :
   return std::make_pair(quotient, remainder);
}

std::pair<int, int> answer = divide(5,2);
 // answer.first == quotient
 // answer.second == remainder

Std::pair本质上是你的结构解决方案,但是已经为你定义好了,并且可以适应任何两种数据类型。

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

我想说,没有首选方法,这完全取决于你将如何处理响应。如果结果将在进一步处理中一起使用,那么结构是有意义的,如果不是,我倾向于将then作为单独的引用传递,除非函数将用于复合语句中:

X =除(X, y, z) +除(a, b, c);

我经常选择在参数列表中通过引用传递“结构”,而不是通过返回新结构的拷贝开销(但这是汗流浃背的小事)。

无效除(整数被除数,整数除数,答案和ans)

我们的参数令人困惑吗?作为引用发送的形参表明值将发生变化(与const引用相反)。合理的命名也可以消除混淆。

对于返回两个值,我使用std::pair(通常是类型定义的)。您应该查看boost::tuple(在c++ 11及更新版本中,有std::tuple),以获得两个以上的返回结果。

随着c++ 17中结构化绑定的引入,返回std::tuple可能会成为可接受的标准。