Returning multiple data items from a function in C

2019-06-16 09:54发布

问题:

I am confused on a couple homework questions I have... Can you return multiple data items from a function by using return()? Can a function only return one value, unless it is a pointer to an array?

I believe that the answer is that a function can return multiple data items by returning a structure. Then, returning a pointer to an array is not the only way - if that is a way?

But there seems to be a lot of discussion on this topic and so I want to make sure I have at least the basic idea correct: You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?

回答1:

With C++0x/C++11 you can use this:

#include <string>
#include <iostream>
#include <tuple>

using namespace std;

tuple<int, unsigned, string, int> getValues()
{
    return tuple<int, unsigned, string, int>(1, 2, "3", 4);
}

int main()
{
    int a;
    unsigned b;
    string c;
    int d;

    tie(a, b, c, d) = getValues();

    cout << a << ", " << b << ", " << c << ", " << d << endl;
    return 0;
}

Compile it with

g++ tuple_test.cpp -std=c++0x -o tuple_test

And and if you run the programm it will output this:

1, 2, 3, 4

But it's better to use references like this (i would say):

void getValues(int& a, unsigned& b, string& c, int& d)
{
    a = 1;
    b = 2;
    c = "3";
    d = 4;
}

int main()
{
    ...
    getValues(a, b, c, d)
    ...
}

Uch thats what I get for not reading the question carefully...

Can a function only return one value, unless it is a pointer to an array?

Yeah you only can return 1 single value, but this single value can include multiply values (struct, class, array).

You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?

True. But when you use pointers it depends on how you use it. When you dynamic allocate it each function call it wont be very efficient and you would need to deallocate the memory manually after usage. When you use a global-array/struct it will be efficient. But can give you problems when you call the function multiply times.



回答2:

In addition to what is already said in this thread, in C++11 you can return structures initialized using uniform initialization:

struct XYZ {
    int x;
    int y;
    int z;
};

XYZ foo() {
    return {1, 2, 3};
}

Personally I prefer returning structures with named members rather than tuples because the latter doesn't provide names for its members.



回答3:

That is correct.

You can however "return" multiple items, by adding parameters that are passed by reference, then writing the multiple results to them.



回答4:

A function can indeed only return one 'thing' with its return statement. That thing can, however, be a pointer (C & C++ arrays are simply pointers in disguise), a reference (a pointer which can't be reseated or array-indexed) or an object, which may encapsulate multiple things.

If you return a structure, you're passing back the entire structure. If you return a pointer or reference, you are returning only the address of the structure - so you had better not return a reference or pointer to a structure that goes out of scope when the function returns! Doing so invokes undefined behavior, which most likely (but not always) is a segmentation fault.



回答5:

If you want a bigger picture about this read about passing parameters by value and passing by reference it also applies for returning parameters.

As you mentioned:

You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?

Lets say you have some structure:

struct BigStructure{
       int array[1000];
       double otherData[1000];
       //... etc
};

and some method:

BigStructure workWhenCopying(BigStructure bigStruct){
      // some work with a structure
      return bigStruct;
}

This method illustrates the case when you pass parameters to the method and return it by value, which means that each time you call this method you are copying the method's argument into another place in memory. This copying takes time and when you have bigger structures it slows down your program run time thus it is more efficient to pass big structures by reference.

void workWithReference(BigStructure & bigStruct){
     // do some work
}

In this case you are not copying whole data structure, just passing the address of the memory where this structure resides. You also don't need a return statement since changes to that structure object will be visible outside this method. But if you will reassign bigStruct to a new memory location it will be visible only within local method: workWithReference

I hope it's more clearer now;)