Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C+返回多个值+;功能 是否有一种从C++函数返回多个值的首选方法?例如,假设一个函数将两个整数相除,并返回商和余数。我通常看到的一种方法是使用参考参数: void divide(int dividend, int divisor, int& quotient, int& remainder); void foo( int& result, int& other_result ); void foo( int* result, int* other_result );_C++_C++17_C++20 - Fatal编程技术网

从C+返回多个值+;功能 是否有一种从C++函数返回多个值的首选方法?例如,假设一个函数将两个整数相除,并返回商和余数。我通常看到的一种方法是使用参考参数: void divide(int dividend, int divisor, int& quotient, int& remainder); void foo( int& result, int& other_result ); void foo( int* result, int* other_result );

从C+返回多个值+;功能 是否有一种从C++函数返回多个值的首选方法?例如,假设一个函数将两个整数相除,并返回商和余数。我通常看到的一种方法是使用参考参数: void divide(int dividend, int divisor, int& quotient, int& remainder); void foo( int& result, int& other_result ); void foo( int* result, int* other_result );,c++,c++17,c++20,C++,C++17,C++20,一种变体是返回一个值并通过参考参数传递另一个值: int divide(int dividend, int divisor, int& remainder); 另一种方法是声明一个包含所有结果的结构,并返回: struct divide_result { int quotient; int remainder; }; divide_result divide(int dividend, int divisor); 这些方法中有一种是普遍首选的,还是有其他建议 编辑:

一种变体是返回一个值并通过参考参数传递另一个值:

int divide(int dividend, int divisor, int& remainder);
另一种方法是声明一个包含所有结果的结构,并返回:

struct divide_result {
    int quotient;
    int remainder;
};

divide_result divide(int dividend, int divisor);
这些方法中有一种是普遍首选的,还是有其他建议


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

备选方案包括数组和,但在这里没有一个是合适的

一些(如历史上的Win32中的Microsoft)倾向于使用参考参数以简化操作,因为很清楚谁分配了资源以及它在堆栈上的外观,减少了结构的扩散,并允许为成功使用单独的返回值


“纯”程序员更喜欢struct,假设它是函数值(这里就是这种情况),而不是函数偶然触及的东西。如果您有一个更复杂的过程,或者有状态,您可能会使用引用(假设您有理由不使用类)。

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

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

对于返回两个值,我使用
std::pair
(通常为typedef'd)。对于两个以上的返回结果,您应该查看
boost::tuple
(在C++11及更新版本中,有
std::tuple

< P>在C++ 17中引入结构化绑定,返回<代码> STD::tuple < /代码>应该成为公认的标准。< /P> <代码> STD::配对除法(int红利,int除数)
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
{ // : return std::make_pair(商,余数); } 标准::配对答案=除法(5,2); //答案.第一个==商 //answer.second==余数
std::pair本质上是您的结构解决方案,但已经为您定义了,并且可以适应任何两种数据类型

我倾向于在这样的函数中使用out-vals,因为我坚持函数返回成功/错误代码的范例,并且我喜欢保持一致

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

x=divide(x,y,z)+divide(a,b,c)

我经常选择在参数列表中通过引用传递“out structures”,而不是通过复制来传递返回新结构的开销(但这会让小事情变得棘手)

void divide(整数除数、整数除数、Answer&ans)


我们的参数令人困惑吗?作为引用发送的参数表示该值将要更改(与常量引用相反)。合理的命名也可以消除混淆。

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

可能的例子:

include "boost/tuple/tuple.hpp"

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

{
  return make_tuple(dividend / divisor,dividend % divisor )
}
包括“boost/tuple/tuple.hpp”
元组除法(整数除数,整数除数)
{
返回生成元组(股息/除数,股息%除数)
}

如果您的函数通过引用返回值,编译器在调用其他函数时无法将其存储在寄存器中,因为理论上,第一个函数可以将传递给它的变量的地址保存在全局可访问变量中,并且任何随后调用的函数都可能更改它,因此编译器将具有(1)在调用其他函数之前,将寄存器中的值保存回内存,(2)在任何此类调用之后需要时,再次从内存中读取该值


如果您通过引用返回,您的程序优化将受到影响。就个人而言,我通常不喜欢返回参数,原因有很多:

  • 在调用中,哪些参数是in,哪些参数是OUT并不总是很明显
  • 您通常必须创建一个局部变量来捕获结果,而返回值可以内联使用(这可能是个好主意,也可能不是,但至少您可以选择)
  • 对我来说,一个函数有一个“门内”和一个“门外”似乎更干净——所有的输入都在这里,所有的输出都在那里
  • 我喜欢让我的论点列表尽可能简短
我对pair/tuple技术也有一些保留。主要是,返回值通常没有自然顺序。代码的读者如何知道result.first是商还是余数?实现者可以更改顺序,这将破坏现有代码。如果值是相同的类型,因此不会生成编译器错误或警告,则这种情况尤其危险。实际上,这些参数也适用于返回参数

下面是另一个代码示例,这一个稍微简单一些:

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;
成对计算结果速度(双风速、双风向角、,
双机空速、双机航向);
配对结果=计算结果速度(25320280,90);

在C(因此也是C++)标准中,使用
div
ldiv
(在C99中,
lldiv
)函数从
(或
)返回结构是有先例的

“混合”
#include <tuple>

std::tuple<int, int> divide(int dividend, int divisor) {
    return  {dividend / divisor, dividend % divisor};
}

#include <iostream>

int main() {
    using namespace std;

    auto [quotient, remainder] = divide(14, 3);

    cout << quotient << ',' << remainder << endl;
}
auto divide(int dividend, int divisor) {
    struct result {int quotient; int remainder;};
    return result {dividend / divisor, dividend % divisor};
}

#include <iostream>

int main() {
    using namespace std;

    auto result = divide(14, 3);

    cout << result.quotient << ',' << result.remainder << endl;

    // or

    auto [quotient, remainder] = divide(14, 3);

    cout << quotient << ',' << remainder << endl;
}
class div{
   public:
      int remainder;

      int quotient(int dividend, int divisor){
         remainder = ...;
         return ...;
      }
};
#  include <tuple>
# include <iostream>

using namespace std; 

tuple < int,int,int,int,int >   cal(int n1, int n2)
{
    return  make_tuple(n1/n2,n1%n2,n1+n2,n1-n2,n1*n2);
}

int main()
{
    int qut,rer,add,sub,mul,a,b;
    cin>>a>>b;
    tie(qut,rer,add,sub,mul)=cal(a,b);
    cout << "quotient= "<<qut<<endl;
    cout << "remainder= "<<rer<<endl;
    cout << "addition= "<<add<<endl;
    cout << "subtraction= "<<sub<<endl;
    cout << "multiplication= "<<mul<<endl;
    return 0;
}
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();
}
int divide(int a,int b,int quo,int &rem)
void foo( int& result, int& other_result );
void foo( int* result, int* other_result );
template<class T>
struct out {
  std::function<void(T)> target;
  out(T* t):target([t](T&& in){ if (t) *t = std::move(in); }) {}
  out(std::optional<T>* t):target([t](T&& in){ if (t) t->emplace(std::move(in)); }) {}
  out(std::aligned_storage_t<sizeof(T), alignof(T)>* t):
    target([t](T&& in){ ::new( (void*)t ) T(std::move(in)); } ) {}
  template<class...Args> // TODO: SFINAE enable_if test
  void emplace(Args&&...args) {
    target( T(std::forward<Args>(args)...) );
  }
  template<class X> // TODO: SFINAE enable_if test
  void operator=(X&&x){ emplace(std::forward<X>(x)); }
  template<class...Args> // TODO: SFINAE enable_if test
  void operator()(Args...&&args){ emplace(std::forward<Args>(args)...); }
};
void foo( out<int> result, out<int> other_result )
struct foo_r { int result; int other_result; };
foo_r foo();
auto&&[result, other_result]=foo();
std::tuple<int, int> foo();
auto&&[result, other_result]=foo();
int result, other_result;
std::tie(result, other_result) = foo();
void foo( std::function<void(int result, int other_result)> );
foo( [&](int result, int other_result) {
  /* code */
} );
void get_all_values( std::function<void(int)> value )
void foo( std::function<void(int, std::function<void(int)>)> result );
foo( [&](int result, auto&& other){ other([&](int other){
  /* code */
}) });
void foo( std::function< void(span<int>) > results )
void foo( std::function< void(span<int>) > results ) {
  int local_buffer[1024];
  std::size_t used = 0;
  auto send_data=[&]{
    if (!used) return;
    results({ local_buffer, used });
    used = 0;
  };
  auto add_datum=[&](int x){
    local_buffer[used] = x;
    ++used;
    if (used == 1024) send_data();
  };
  auto add_data=[&](gsl::span<int const> xs) {
    for (auto x:xs) add_datum(x);
  };
  for (int i = 0; i < 7+(1<<20); ++i) {
    add_datum(i);
  }
  send_data(); // any leftover
}
std::function<void(std::function<void(int result, int other_result)>)> foo(int input);
foo(7)([&](int result, int other_result){ /* code */ });
template<class...Args>
struct broadcaster;

broadcaster<int, int> foo();
foo( int_source )( int_dest1, int_dest2 );
static struct SomeReturnType {int a,b,c; string str;} SomeFunction()
{
  return {1,2,3,string("hello world")}; // make sure you return values in the right order!
}
 SomeReturnType st = SomeFunction();
 cout << "a "   << st.a << endl;
 cout << "b "   << st.b << endl;
 cout << "c "   << st.c << endl;
 cout << "str " << st.str << endl;
#include <iostream>
using namespace std;

// different values of [operate] can return different number.
int yourFunction(int a, int b, int operate)
{
    a = 1;
    b = 2;

    if (operate== 1)
    {
        return a;
    }
    else
    {
        return b;
    }
}

int main()
{
    int a, b;

    a = yourFunction(a, b, 1); // get return 1
    b = yourFunction(a, b, 2); // get return 2

    return 0;
}