Is there a preferred way to return multiple values from a C++ function? For example, imagine a function that divides two integers and returns both the quotient and the remainder. One way I commonly see is to use reference parameters:
是否有一种从c++函数返回多个值的首选方法?例如,假设有一个函数可以分割两个整数,并同时返回商和余数。我通常看到的一种方法是使用参考参数:
void divide(int dividend, int divisor, int& quotient, int& remainder);
A variation is to return one value and pass the other through a reference parameter:
变化是返回一个值,并通过引用参数传递另一个值:
int divide(int dividend, int divisor, int& remainder);
Another way would be to declare a struct to contain all of the results and return that:
另一种方法是声明一个包含所有结果的struct并返回:
struct divide_result {
int quotient;
int remainder;
};
divide_result divide(int dividend, int divisor);
Is one of these ways generally preferred, or are there other suggestions?
这些方法一般都是首选还是有其他的建议?
Edit: In the real-world code, there may be more than two results. They may also be of different types.
编辑:在真实的代码中,可能有两个以上的结果。它们也可能是不同类型的。
18 个解决方案
#1
152
For returning two values I use a std::pair
(usually typedef'd). You should look at boost::tuple
(in C++11 and newer, there's std::tuple
) for more than two return results.
对于返回两个值,我使用std::pair(通常是typedef d)。您应该查看boost::tuple(在c++ 11和更新版本中,有std:::tuple),以获得两个以上的返回结果。
With introduction of structured binding in C++ 17, returning std::tuple
should probably become accepted standard.
在c++ 17中引入结构化绑定后,返回std::tuple应该成为公认的标准。
#2
105
Personally, I generally dislike return parameters for a number of reasons:
就我个人而言,出于以下几个原因,我通常不喜欢返回参数:
- it is not always obvious in the invocation which parameters are ins and which are outs
- 在调用中,并不总是很明显哪些参数是in,哪些是out
- you generally have to create a local variable to catch the result, while return values can be used inline (which may or may not be a good idea, but at least you have the option)
- 您通常需要创建一个本地变量来捕获结果,而返回值可以使用内联(这可能是或者不是一个好主意,但至少您可以选择)
- it seems cleaner to me to have an "in door" and an "out door" to a function -- all the inputs go in here, all the outputs come out there
- 对我来说,有一个“在门”和一个“出门”的功能似乎更清洁,所有的输入都在这里,所有的输出都出来了。
- I like to keep my argument lists as short as possible
- 我喜欢把我的论点清单尽可能地短
I also have some reservations about the pair/tuple technique. Mainly, there is often no natural order to the return values. How is the reader of the code to know whether result.first is the quotient or the remainder? And the implementer could change the order, which would break existing code. This is especially insidious if the values are the same type so that no compiler error or warning would be generated. Actually, these arguments apply to return parameters as well.
我对结对/元组技术也有所保留。通常,返回值通常没有自然顺序。如何读取代码以知道结果。首先是商还是余数?实现者可以改变顺序,这会破坏现有的代码。如果值是相同的类型,这样就不会生成任何编译器错误或警告,这一点尤其危险。实际上,这些参数也适用于返回参数。
Here's another code example, this one a bit less trivial:
这是另一个代码示例,这个例子不那么简单:
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;
Does this print groundspeed and course, or course and groundspeed? It's not obvious.
这是打印地面速度和航向,还是航向和地面速度?这不是显而易见的。
Compare to this:
比较:
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;
I think this is clearer.
我认为这更清楚。
So I think my first choice in general is the struct technique. The pair/tuple idea is likely a great solution in certain cases. I'd like to avoid the return parameters when possible.
所以我认为我的第一选择是结构技术。对/元组思想在某些情况下可能是一个很好的解决方案。我希望尽可能避免返回参数。
#3
97
In C++11 you can:
在c++中11,您可以:
#include <tuple>
std::tuple<int, int> divide(int dividend, int divisor) {
return std::make_tuple(dividend / divisor, dividend % divisor);
}
#include <iostream>
int main() {
using namespace std;
int quotient, remainder;
tie(quotient, remainder) = divide(14, 3);
cout << quotient << ',' << remainder << endl;
}
In C++17:
在c++中17:
#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;
}
or with structs:
或与结构:
#include <tuple>
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;
}
#4
21
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 is essentially your struct solution, but already defined for you, and ready to adapt to any two data types.
pair本质上是您的struct解决方案,但是已经为您定义了,可以适应任何两种数据类型。
#5
13
It's entirely dependent upon the actual function and the meaning of the multiple values, and their sizes:
它完全取决于实际的函数和多重值的意义,以及它们的大小:
- If they're related as in your fraction example, then I'd go with a struct or class instance.
- 如果它们像你的分数例子一样相关,那么我就用struct或类实例。
- If they're not really related and can't be grouped into a class/struct then perhaps you should refactor your method into two.
- 如果它们不是真的相关并且不能被分组到一个类/结构中,那么也许你应该将你的方法重构为两个。
- Depending upon the in-memory size of the values you're returning, you may want to return a pointer to a class instance or struct, or use reference parameters.
- 根据要返回的值的内存大小,您可能希望返回指向类实例或结构的指针,或者使用引用参数。
#6
11
The OO solution for this is to create a ratio class. It wouldn't take any extra code (would save some), would be significantly cleaner/clearer, and would give you some extra refactorings letting you clean up code outside this class as well.
面向对象的解决方案是创建一个比例类。它不会接受任何额外的代码(会节省一些),会明显的更干净/更清晰,并且会给您一些额外的重构,让您在这个类之外清理代码。
Actually I think someone recommended returning a structure, which is close enough but hides the intent that this needs to be a fully thought-out class with constructor and a few methods, in fact, the "method" that you originally mentioned (as returning the pair) should most likely be a member of this class returning an instance of itself.
其实我觉得有人建议返回一个结构,这是足够接近但隐藏意图,这需要一个完全熟虑类构造函数和几个方法,事实上,你最初提到的“方法”(如返回副)最有可能应该属于这个类的一个实例返回本身。
I know your example was just an "Example", but the fact is that unless your function is doing way more than any function should be doing, if you want it to return multiple values you are almost certainly missing an object.
我知道你的例子只是一个“例子”,但事实是,除非你的函数比任何函数都要做得多,否则如果你想让它返回多个值,你几乎肯定会丢失一个对象。
Don't be afraid to create these tiny classes to do little pieces of work--that's the magic of OO--you end up breaking it down until every method is very small and simple and every class small and understandable.
不要害怕创建这些小类来完成小的工作——这就是OO的神奇之处——您最终会将其分解,直到每个方法都非常小和简单,每个类都很小并且可以理解。
Another thing that should have been an indicator that something was wrong: in OO you have essentially no data--OO isn't about passing around data, a class needs to manage and manipulate it's own data internally, any data passing (including accessors) is a sign that you may need to rethink something..
另一件事应该是某种指示出了问题:在OO中,你基本上没有数据——OO不是关于传递数据,一个类需要在内部管理和操作它自己的数据,任何数据传递(包括访问器)都表明你可能需要重新考虑一些事情。
#7
8
There is precedent for returning structures in the C (and hence C++) standard with the div
, ldiv
(and, in C99, lldiv
) functions from <stdlib.h>
(or <cstdlib>
).
在使用div、ldiv(以及C99中的lldiv)函数返回C(因此是c++)标准中的结构的情况是有先例的。h >(或< cstdlib >)。
The 'mix of return value and return parameters' is usually the least clean.
“返回值和返回参数的组合”通常是最不干净的。
Having a function return a status and return data via return parameters is sensible in C; it is less obviously sensible in C++ where you could use exceptions to relay failure information instead.
函数返回状态并通过返回参数返回数据在C中是合理的;在c++中,您可以使用异常来替代传递故障信息。
If there are more than two return values, then a structure-like mechanism is probably best.
如果返回值超过两个,那么最好使用类似结构的机制。
#8
8
With C++17 you can also return one ore more unmovable/uncopyable values (in certain cases). The possibility to return unmovable types come via the new guaranteed return value optimization, and it composes nicely with aggregates, and what can be called templated constructors.
使用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();
}
The pretty thing about this is that it is guaranteed to not cause any copying or moving. You can make the example many
struct variadic too. More details:
这样做的好处在于,它保证不会导致任何复制或移动。你也可以让这个例子有很多结构变量。更多的细节:
为c++ 17变量模板“构建演绎指南”返回变量聚集(struct)和语法
#9
3
If your function returns a value via reference, the compiler cannot store it in a register when calling other functions because, theoretically, the first function can save the address of the variable passed to it in a globally accessible variable, and any subsecuently called functions may change it, so the compiler will have (1) save the value from registers back to memory before calling other functions and (2) re-read it when it is needed from the memory again after any of such calls.
如果你通过引用函数返回一个值,编译器不能存储在寄存器当调用其他函数,因为从理论上讲,第一个函数可以保存变量的地址传递给它的全局变量,和任何subsecuently称为功能可能改变它,所以编译器会有(1)将值从寄存器保存到内存之前调用其他函数和(2)重读的时候需要从内存后再任何这样的调用。
If you return by reference, optimization of your program will suffer
如果您通过引用返回,程序的优化将会受到影响
#10
3
Here, i am writing a program that is returning multiple values(more than two values) in c++. This program is executable in c++14 (G++4.9.2). program is like a calculator.
在这里,我正在编写一个程序,它使用c++返回多个值(超过两个值)。这个程序在c++14 (G+ 4.9.2)中是可执行的。程序就像一个计算器。
# 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;
}
So, you can clearly understand that in this way you can return multiple values from a function. using std::pair only 2 values can be returned while std::tuple can return more than two values.
因此,你可以清楚地理解,这样你可以从一个函数返回多个值。使用std::pair只有两个值可以返回,而std::tuple可以返回两个以上的值。
#11
3
Use a struct or a class for the return value. Using std::pair
may work for now, but
返回值使用结构体或类。使用std::pair现在可以工作,但是。
- it's inflexible if you decide later you want more info returned;
- 如果你决定以后你想要返回更多的信息,这是不灵活的;
- it's not very clear from the function's declaration in the header what is being returned and in what order.
- 在header中,从函数的声明中不太清楚返回的是什么,以及什么顺序。
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.
对于任何使用您的函数的人来说,返回一个具有自文档化成员变量名的结构可能不太容易出错。给我的同事戴上帽子一会儿,您的divide_result结构对我这个您的函数的潜在用户来说很容易在2秒后立即理解。使用ouput参数或神秘的对和元组将花费更多的时间来通读,并且可能使用不正确。而且很可能在使用了几次函数之后,我仍然不记得参数的正确顺序。
#12
2
I tend to use out-vals in functions like this, because I stick to the paradigm of a function returning success/error codes and I like to keep things uniform.
我倾向于在这样的函数中使用outvals,因为我遵循函数返回成功/错误代码的范例,而且我喜欢保持一致。
#13
1
Alternatives include arrays, generators, and inversion of control, but none is appropriate here.
替代方法包括数组、生成器和反转控制,但在这里都不合适。
Some (e.g. Microsoft in historical Win32) tend to use reference parameters for simplicity, because it's clear who allocates and how it will look on the stack, reduces the proliferation of structures, and allows a separate return value for success.
有些(例如Microsoft in history Win32)倾向于使用引用参数来实现简单性,因为很清楚是谁分配以及它在堆栈上的样子,减少了结构的增殖,并允许一个单独的返回值来获得成功。
"Pure" programmers prefer the struct, assuming it is the function value (as is the case here), rather than something that's touched incidentally by the function. If you had a more complicated procedure, or something with state, you'd probably use references (assuming you have a reason for not using a class).
“纯粹的”程序员更喜欢结构,假设它是函数值(就像这里的情况一样),而不是由函数附带的东西。如果您有一个更复杂的过程或具有状态的东西,您可能会使用引用(假设您有不使用类的理由)。
#14
1
I'd say there is no preferred method, it all depends on what you're going to do with the response. If the results are going to be used together in further processing then structures make sense, if not I'd tend to pass then as individual references unless the function was going to be used in a composite statement:
我想说没有首选的方法,这完全取决于你对响应做什么。如果结果将一起用于进一步的处理那么结构是有意义的,如果不是的话,我倾向于作为单独的引用来传递除非函数将用于复合语句:
x = divide( x, y, z ) + divide( a, b, c );
x =除(x, y, z) +除(a, b, c);
I often choose to pass 'out structures' by reference in the parameter list rather than having the pass by copy overhead of returning a new structure (but this is sweating the small stuff).
我经常选择在参数列表中引用“out structure”,而不是通过复制返回新结构的开销(但这是在流汗)。
void divide(int dividend, int divisor, Answer &ans)
空分(int dividend, int divisor, Answer &ans)
Are out parameters confusing? A parameter sent as reference suggests the value is going to change (as opposed to a const reference). Sensible naming also removes confusion.
out参数混乱吗?作为引用发送的参数表明该值将更改(而不是const引用)。合理的命名也可以消除混淆。
#15
1
rather than returning multiple values,just return one of them and make a reference of others in the required function for eg:
与其返回多个值,不如返回其中一个并在所需函数中引用其他值,例如:
int divide(int a,int b,int quo,int &rem)
#16
0
Why do you insist on a function with multiple return values? With OOP you can use a class offering a regular function with a single return value, and any number of additional "return values" like below. The advantage is that the caller has a choice of looking at the extra data members, but is not required to do this. This is the preferred method for complicated data base or networking calls, where lots of additional return info may be needed in case errors occur.
为什么要坚持使用具有多个返回值的函数?在OOP中,您可以使用一个类提供一个具有单一返回值的正则函数,以及如下所示的任意数量的“返回值”。其优点是,调用者可以选择查看额外的数据成员,但不需要这样做。这是用于复杂数据库或网络调用的首选方法,在这种情况下,如果发生错误,可能需要许多额外的返回信息。
To answer your original question, this example has a method to return the quotient, which is what most callers may need, and additionally, after the method call, you can get the remainder as a data member.
要回答最初的问题,这个示例有一个返回商的方法,这是大多数调用者可能需要的,此外,在方法调用之后,您可以作为数据成员获得剩余。
class div{
public:
int remainder;
int quotient(int dividend, int divisor){
remainder = ...;
return ...;
}
};
#17
0
Boost tuple would be my preferred choice for a generalized system of returning more than one value from a function.
对于从函数返回多个值的广义系统来说,Boost tuple是我的首选。
Possible example:
可能的例子:
include "boost/tuple/tuple.hpp"
tuple <int,int> divide( int dividend,int divisor )
{
return make_tuple(dividend / divisor,dividend % divisor )
}
#18
0
We can declare the function such that, it returns a structure type user defined variable or a pointer to it . And by the property of a structure, we know that a structure in C can hold multiple values of asymmetrical types (i.e. one int variable, four char variables, two float variables and so on…)
我们可以声明该函数,以便它返回用户定义的结构类型变量或指向它的指针。根据结构的性质,我们知道C中的结构可以包含多个不对称类型的值(即一个int变量、四个char变量、两个浮点变量等等)。
#1
152
For returning two values I use a std::pair
(usually typedef'd). You should look at boost::tuple
(in C++11 and newer, there's std::tuple
) for more than two return results.
对于返回两个值,我使用std::pair(通常是typedef d)。您应该查看boost::tuple(在c++ 11和更新版本中,有std:::tuple),以获得两个以上的返回结果。
With introduction of structured binding in C++ 17, returning std::tuple
should probably become accepted standard.
在c++ 17中引入结构化绑定后,返回std::tuple应该成为公认的标准。
#2
105
Personally, I generally dislike return parameters for a number of reasons:
就我个人而言,出于以下几个原因,我通常不喜欢返回参数:
- it is not always obvious in the invocation which parameters are ins and which are outs
- 在调用中,并不总是很明显哪些参数是in,哪些是out
- you generally have to create a local variable to catch the result, while return values can be used inline (which may or may not be a good idea, but at least you have the option)
- 您通常需要创建一个本地变量来捕获结果,而返回值可以使用内联(这可能是或者不是一个好主意,但至少您可以选择)
- it seems cleaner to me to have an "in door" and an "out door" to a function -- all the inputs go in here, all the outputs come out there
- 对我来说,有一个“在门”和一个“出门”的功能似乎更清洁,所有的输入都在这里,所有的输出都出来了。
- I like to keep my argument lists as short as possible
- 我喜欢把我的论点清单尽可能地短
I also have some reservations about the pair/tuple technique. Mainly, there is often no natural order to the return values. How is the reader of the code to know whether result.first is the quotient or the remainder? And the implementer could change the order, which would break existing code. This is especially insidious if the values are the same type so that no compiler error or warning would be generated. Actually, these arguments apply to return parameters as well.
我对结对/元组技术也有所保留。通常,返回值通常没有自然顺序。如何读取代码以知道结果。首先是商还是余数?实现者可以改变顺序,这会破坏现有的代码。如果值是相同的类型,这样就不会生成任何编译器错误或警告,这一点尤其危险。实际上,这些参数也适用于返回参数。
Here's another code example, this one a bit less trivial:
这是另一个代码示例,这个例子不那么简单:
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;
Does this print groundspeed and course, or course and groundspeed? It's not obvious.
这是打印地面速度和航向,还是航向和地面速度?这不是显而易见的。
Compare to this:
比较:
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;
I think this is clearer.
我认为这更清楚。
So I think my first choice in general is the struct technique. The pair/tuple idea is likely a great solution in certain cases. I'd like to avoid the return parameters when possible.
所以我认为我的第一选择是结构技术。对/元组思想在某些情况下可能是一个很好的解决方案。我希望尽可能避免返回参数。
#3
97
In C++11 you can:
在c++中11,您可以:
#include <tuple>
std::tuple<int, int> divide(int dividend, int divisor) {
return std::make_tuple(dividend / divisor, dividend % divisor);
}
#include <iostream>
int main() {
using namespace std;
int quotient, remainder;
tie(quotient, remainder) = divide(14, 3);
cout << quotient << ',' << remainder << endl;
}
In C++17:
在c++中17:
#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;
}
or with structs:
或与结构:
#include <tuple>
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;
}
#4
21
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 is essentially your struct solution, but already defined for you, and ready to adapt to any two data types.
pair本质上是您的struct解决方案,但是已经为您定义了,可以适应任何两种数据类型。
#5
13
It's entirely dependent upon the actual function and the meaning of the multiple values, and their sizes:
它完全取决于实际的函数和多重值的意义,以及它们的大小:
- If they're related as in your fraction example, then I'd go with a struct or class instance.
- 如果它们像你的分数例子一样相关,那么我就用struct或类实例。
- If they're not really related and can't be grouped into a class/struct then perhaps you should refactor your method into two.
- 如果它们不是真的相关并且不能被分组到一个类/结构中,那么也许你应该将你的方法重构为两个。
- Depending upon the in-memory size of the values you're returning, you may want to return a pointer to a class instance or struct, or use reference parameters.
- 根据要返回的值的内存大小,您可能希望返回指向类实例或结构的指针,或者使用引用参数。
#6
11
The OO solution for this is to create a ratio class. It wouldn't take any extra code (would save some), would be significantly cleaner/clearer, and would give you some extra refactorings letting you clean up code outside this class as well.
面向对象的解决方案是创建一个比例类。它不会接受任何额外的代码(会节省一些),会明显的更干净/更清晰,并且会给您一些额外的重构,让您在这个类之外清理代码。
Actually I think someone recommended returning a structure, which is close enough but hides the intent that this needs to be a fully thought-out class with constructor and a few methods, in fact, the "method" that you originally mentioned (as returning the pair) should most likely be a member of this class returning an instance of itself.
其实我觉得有人建议返回一个结构,这是足够接近但隐藏意图,这需要一个完全熟虑类构造函数和几个方法,事实上,你最初提到的“方法”(如返回副)最有可能应该属于这个类的一个实例返回本身。
I know your example was just an "Example", but the fact is that unless your function is doing way more than any function should be doing, if you want it to return multiple values you are almost certainly missing an object.
我知道你的例子只是一个“例子”,但事实是,除非你的函数比任何函数都要做得多,否则如果你想让它返回多个值,你几乎肯定会丢失一个对象。
Don't be afraid to create these tiny classes to do little pieces of work--that's the magic of OO--you end up breaking it down until every method is very small and simple and every class small and understandable.
不要害怕创建这些小类来完成小的工作——这就是OO的神奇之处——您最终会将其分解,直到每个方法都非常小和简单,每个类都很小并且可以理解。
Another thing that should have been an indicator that something was wrong: in OO you have essentially no data--OO isn't about passing around data, a class needs to manage and manipulate it's own data internally, any data passing (including accessors) is a sign that you may need to rethink something..
另一件事应该是某种指示出了问题:在OO中,你基本上没有数据——OO不是关于传递数据,一个类需要在内部管理和操作它自己的数据,任何数据传递(包括访问器)都表明你可能需要重新考虑一些事情。
#7
8
There is precedent for returning structures in the C (and hence C++) standard with the div
, ldiv
(and, in C99, lldiv
) functions from <stdlib.h>
(or <cstdlib>
).
在使用div、ldiv(以及C99中的lldiv)函数返回C(因此是c++)标准中的结构的情况是有先例的。h >(或< cstdlib >)。
The 'mix of return value and return parameters' is usually the least clean.
“返回值和返回参数的组合”通常是最不干净的。
Having a function return a status and return data via return parameters is sensible in C; it is less obviously sensible in C++ where you could use exceptions to relay failure information instead.
函数返回状态并通过返回参数返回数据在C中是合理的;在c++中,您可以使用异常来替代传递故障信息。
If there are more than two return values, then a structure-like mechanism is probably best.
如果返回值超过两个,那么最好使用类似结构的机制。
#8
8
With C++17 you can also return one ore more unmovable/uncopyable values (in certain cases). The possibility to return unmovable types come via the new guaranteed return value optimization, and it composes nicely with aggregates, and what can be called templated constructors.
使用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();
}
The pretty thing about this is that it is guaranteed to not cause any copying or moving. You can make the example many
struct variadic too. More details:
这样做的好处在于,它保证不会导致任何复制或移动。你也可以让这个例子有很多结构变量。更多的细节:
为c++ 17变量模板“构建演绎指南”返回变量聚集(struct)和语法
#9
3
If your function returns a value via reference, the compiler cannot store it in a register when calling other functions because, theoretically, the first function can save the address of the variable passed to it in a globally accessible variable, and any subsecuently called functions may change it, so the compiler will have (1) save the value from registers back to memory before calling other functions and (2) re-read it when it is needed from the memory again after any of such calls.
如果你通过引用函数返回一个值,编译器不能存储在寄存器当调用其他函数,因为从理论上讲,第一个函数可以保存变量的地址传递给它的全局变量,和任何subsecuently称为功能可能改变它,所以编译器会有(1)将值从寄存器保存到内存之前调用其他函数和(2)重读的时候需要从内存后再任何这样的调用。
If you return by reference, optimization of your program will suffer
如果您通过引用返回,程序的优化将会受到影响
#10
3
Here, i am writing a program that is returning multiple values(more than two values) in c++. This program is executable in c++14 (G++4.9.2). program is like a calculator.
在这里,我正在编写一个程序,它使用c++返回多个值(超过两个值)。这个程序在c++14 (G+ 4.9.2)中是可执行的。程序就像一个计算器。
# 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;
}
So, you can clearly understand that in this way you can return multiple values from a function. using std::pair only 2 values can be returned while std::tuple can return more than two values.
因此,你可以清楚地理解,这样你可以从一个函数返回多个值。使用std::pair只有两个值可以返回,而std::tuple可以返回两个以上的值。
#11
3
Use a struct or a class for the return value. Using std::pair
may work for now, but
返回值使用结构体或类。使用std::pair现在可以工作,但是。
- it's inflexible if you decide later you want more info returned;
- 如果你决定以后你想要返回更多的信息,这是不灵活的;
- it's not very clear from the function's declaration in the header what is being returned and in what order.
- 在header中,从函数的声明中不太清楚返回的是什么,以及什么顺序。
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.
对于任何使用您的函数的人来说,返回一个具有自文档化成员变量名的结构可能不太容易出错。给我的同事戴上帽子一会儿,您的divide_result结构对我这个您的函数的潜在用户来说很容易在2秒后立即理解。使用ouput参数或神秘的对和元组将花费更多的时间来通读,并且可能使用不正确。而且很可能在使用了几次函数之后,我仍然不记得参数的正确顺序。
#12
2
I tend to use out-vals in functions like this, because I stick to the paradigm of a function returning success/error codes and I like to keep things uniform.
我倾向于在这样的函数中使用outvals,因为我遵循函数返回成功/错误代码的范例,而且我喜欢保持一致。
#13
1
Alternatives include arrays, generators, and inversion of control, but none is appropriate here.
替代方法包括数组、生成器和反转控制,但在这里都不合适。
Some (e.g. Microsoft in historical Win32) tend to use reference parameters for simplicity, because it's clear who allocates and how it will look on the stack, reduces the proliferation of structures, and allows a separate return value for success.
有些(例如Microsoft in history Win32)倾向于使用引用参数来实现简单性,因为很清楚是谁分配以及它在堆栈上的样子,减少了结构的增殖,并允许一个单独的返回值来获得成功。
"Pure" programmers prefer the struct, assuming it is the function value (as is the case here), rather than something that's touched incidentally by the function. If you had a more complicated procedure, or something with state, you'd probably use references (assuming you have a reason for not using a class).
“纯粹的”程序员更喜欢结构,假设它是函数值(就像这里的情况一样),而不是由函数附带的东西。如果您有一个更复杂的过程或具有状态的东西,您可能会使用引用(假设您有不使用类的理由)。
#14
1
I'd say there is no preferred method, it all depends on what you're going to do with the response. If the results are going to be used together in further processing then structures make sense, if not I'd tend to pass then as individual references unless the function was going to be used in a composite statement:
我想说没有首选的方法,这完全取决于你对响应做什么。如果结果将一起用于进一步的处理那么结构是有意义的,如果不是的话,我倾向于作为单独的引用来传递除非函数将用于复合语句:
x = divide( x, y, z ) + divide( a, b, c );
x =除(x, y, z) +除(a, b, c);
I often choose to pass 'out structures' by reference in the parameter list rather than having the pass by copy overhead of returning a new structure (but this is sweating the small stuff).
我经常选择在参数列表中引用“out structure”,而不是通过复制返回新结构的开销(但这是在流汗)。
void divide(int dividend, int divisor, Answer &ans)
空分(int dividend, int divisor, Answer &ans)
Are out parameters confusing? A parameter sent as reference suggests the value is going to change (as opposed to a const reference). Sensible naming also removes confusion.
out参数混乱吗?作为引用发送的参数表明该值将更改(而不是const引用)。合理的命名也可以消除混淆。
#15
1
rather than returning multiple values,just return one of them and make a reference of others in the required function for eg:
与其返回多个值,不如返回其中一个并在所需函数中引用其他值,例如:
int divide(int a,int b,int quo,int &rem)
#16
0
Why do you insist on a function with multiple return values? With OOP you can use a class offering a regular function with a single return value, and any number of additional "return values" like below. The advantage is that the caller has a choice of looking at the extra data members, but is not required to do this. This is the preferred method for complicated data base or networking calls, where lots of additional return info may be needed in case errors occur.
为什么要坚持使用具有多个返回值的函数?在OOP中,您可以使用一个类提供一个具有单一返回值的正则函数,以及如下所示的任意数量的“返回值”。其优点是,调用者可以选择查看额外的数据成员,但不需要这样做。这是用于复杂数据库或网络调用的首选方法,在这种情况下,如果发生错误,可能需要许多额外的返回信息。
To answer your original question, this example has a method to return the quotient, which is what most callers may need, and additionally, after the method call, you can get the remainder as a data member.
要回答最初的问题,这个示例有一个返回商的方法,这是大多数调用者可能需要的,此外,在方法调用之后,您可以作为数据成员获得剩余。
class div{
public:
int remainder;
int quotient(int dividend, int divisor){
remainder = ...;
return ...;
}
};
#17
0
Boost tuple would be my preferred choice for a generalized system of returning more than one value from a function.
对于从函数返回多个值的广义系统来说,Boost tuple是我的首选。
Possible example:
可能的例子:
include "boost/tuple/tuple.hpp"
tuple <int,int> divide( int dividend,int divisor )
{
return make_tuple(dividend / divisor,dividend % divisor )
}
#18
0
We can declare the function such that, it returns a structure type user defined variable or a pointer to it . And by the property of a structure, we know that a structure in C can hold multiple values of asymmetrical types (i.e. one int variable, four char variables, two float variables and so on…)
我们可以声明该函数,以便它返回用户定义的结构类型变量或指向它的指针。根据结构的性质,我们知道C中的结构可以包含多个不对称类型的值(即一个int变量、四个char变量、两个浮点变量等等)。