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

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

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


当前回答

在c++ 17中,你还可以返回一个或多个不可移动/不可复制的值(在某些情况下)。通过新的有保证的返回值优化,可以返回不可移动的类型,并且可以很好地与聚合和模板化构造函数组合在一起。

template<typename T1,typename T2,typename T3>
struct many {
  T1 a;
  T2 b;
  T3 c;
};

// guide:
template<class T1, class T2, class T3>
many(T1, T2, T3) -> many<T1, T2, T3>;

auto f(){ return many{string(),5.7, unmovable()}; }; 

int main(){
   // in place construct x,y,z with a string, 5.7 and unmovable.
   auto [x,y,z] = f();
}

这样做的好处是,它保证不会引起任何复制或移动。你也可以让这个例子有很多可变结构。更多的细节:

返回c++ 17可变变量模板“构造推导指南”的可变变量聚合(struct)和语法

其他回答

如果你通过引用函数返回一个值,编译器不能存储在寄存器当调用其他函数,因为从理论上讲,第一个函数可以保存变量的地址传递给它的全局变量,和任何subsecuently称为功能可能改变它,所以编译器会有(1)将值从寄存器保存到内存之前调用其他函数和(2)重读的时候需要从内存后再任何这样的调用。

如果通过引用返回,程序的优化将受到影响

为什么坚持使用具有多个返回值的函数?在OOP中,你可以使用一个类,它提供一个常规函数和一个单一的返回值,以及如下所示的任意数量的额外“返回值”。这样做的好处是调用者可以选择查看额外的数据成员,但并不要求必须这样做。对于复杂的数据库或网络调用,这是首选的方法,在这些调用中,如果发生错误,可能需要大量额外的返回信息。

为了回答您最初的问题,这个示例有一个返回商的方法,这是大多数调用者可能需要的,此外,在方法调用之后,您可以获得作为数据成员的余数。

class div{
   public:
      int remainder;

      int quotient(int dividend, int divisor){
         remainder = ...;
         return ...;
      }
};

使用结构体或类作为返回值。使用std::pair可能暂时有效,但是

如果你决定以后要返回更多信息,这是不灵活的; 从函数头中的声明来看,不太清楚返回的是什么以及返回的顺序。

Returning a structure with self-documenting member variable names will likely be less bug-prone for anyone using your function. Putting my coworker hat on for a moment, your divide_result structure is easy for me, a potential user of your function, to immediately understand after 2 seconds. Messing around with ouput parameters or mysterious pairs and tuples would take more time to read through and may be used incorrectly. And most likely even after using the function a few times I still won't remember the correct order of the arguments.

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

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

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