Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return array in a function

People also ask

How do you return an array from a function in JavaScript?

JavaScript doesn't support functions that return multiple values. However, you can wrap multiple values into an array or an object and return the array or the object. Use destructuring assignment syntax to unpack values from the array, or properties from objects.

How do you bring an array to a function?

To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.


In this case, your array variable arr can actually also be treated as a pointer to the beginning of your array's block in memory, by an implicit conversion. This syntax that you're using:

int fillarr(int arr[])

Is kind of just syntactic sugar. You could really replace it with this and it would still work:

int fillarr(int* arr)

So in the same sense, what you want to return from your function is actually a pointer to the first element in the array:

int* fillarr(int arr[])

And you'll still be able to use it just like you would a normal array:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}

C++ functions can't return C-style arrays by value. The closest thing is to return a pointer. Furthermore, an array type in the argument list is simply converted to a pointer.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

You can improve it by using an array references for the argument and return, which prevents the decay:

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

With Boost or C++11, pass-by-reference is only optional and the syntax is less mind-bending:

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

The array template simply generates a struct containing a C-style array, so you can apply object-oriented semantics yet retain the array's original simplicity.


In C++11, you can return std::array.

#include <array>
using namespace std;

array<int, 5> fillarr(int arr[])
{
    array<int, 5> arr2;
    for(int i=0; i<5; ++i) {
        arr2[i]=arr[i]*2;
    }
    return arr2;
}

$8.3.5/8 states-

"Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays of pointers to functions."

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}

the answer may depend a bit on how you plan to use that function. For the simplest answer, lets decide that instead of an array, what you really want is a vector. Vectors are nice because the look for all the world like boring, ordinary values you can store in regular pointers. We'll look at other options and why you want them afterwards:

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

This will do exactly what you expect it to do. The upside is that std::vector takes care of making sure everything is handled cleanly. the downside is that this copies a very large amount of data, if your array is large. In fact it copies every element of the array twice. first it copies the vector so that the function can use it as a parameter. then it copies it again to return it to the caller. If you can handle managing the vector yourself, you can do things quite a bit more easily. (it may copy it a third time if the caller needs to store it in a variable of some sort to do more calculation)

It looks like what you're really trying to do is just populate a collection. if you don't have a specific reason to return a new instance of a collection, then don't. we can do it like this

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

this way you get a reference to the array passed to the function, not a private copy of it. any changes you make to the parameter are seen by the caller. You could return a reference to it if you want, but that's not really a great idea, since it sort of implies that you're getting something different from what you passed.

If you really do need a new instance of the collection, but want to avoid having it on the stack (and all the copying that entails), you need to create some kind of contract for how that instance is handled. the easiest way to do that is to use a smart pointer, which keeps the referenced instance around as long as anyone is holding onto it. It goes away cleanly if it goes out of scope. That would look like this.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

For the most part, using *myArr works identically to using a plain vanilla vector. This example also modifies the parameter list by adding the const keyword. Now you get a reference without copying it, but you can't modify it, so the caller knows it'll be the same as before the function got to it.

All of this is swell, but idiomatic c++ rarely works with collections as a whole. More normally, you will be using iterators over those collections. that would look something more like this

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

Using it looks a bit odd if you're not used to seeing this style.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

foo now 'points to' the beginning of the modified arr.

What's really nice about this is that it works equally well on vector as on plain C arrays and many other types of collection, for example

int arr[100];
int *foo = fillarr(arr, arr+100);

Which now looks an awful lot like the plain pointer examples given elsewhere in this question.