35

We can pass reference of an array to a function like:

void f(int (&a)[5]);

int x[5];
f(x);     //okay
int y[6];
f(y);     //error - type of y is not `int (&)[5]`.

Or even better, we can write a function template:

template<size_t N>
void f(int (&a)[N]); //N is size of the array!

int x[5];
f(x);     //okay - N becomes 5
int y[6];
f(y);     //okay - N becomes 6

Now my question is, how to return reference of an array from a function?

I want to return array of folllowing types from a function:

int a[N];
int a[M][N];
int (*a)[N];
int (*a)[M][N];

where M and N is known at compile time!

What are general rules for passing and returning compile-time reference of an array to and from a function? How can we pass reference of an array of type int (*a)[M][N] to a function?

EDIT:

Adam commented : int (*a)[N] is not an array, it's a pointer to an array.

Yes. But one dimension is known at compile time! How can we pass this information which is known at compile time, to a function?

Nawaz
  • 353,942
  • 115
  • 666
  • 851

6 Answers6

47

If you want to return a reference to an array from a function, the declaration would look like this:

// an array
int global[10];

// function returning a reference to an array
int (&f())[10] {
   return global;
}

The declaration of a function returning a reference to an array looks the same as the declaration of a variable that is a reference to an array - only that the function name is followed by (), which may contain parameter declarations:

int (&variable)[1][2];
int (&functionA())[1][2];
int (&functionB(int param))[1][2];

Such declarations can be made much clearer by using a typedef:

typedef int array_t[10];

array_t& f() {
   return global;
}

If you want it to get really confusing, you can declare a function that takes a reference to an array and also returns such a reference:

template<int N, int M>
int (&f(int (&param)[M][N]))[M][N] {
   return param;
}

Pointers to arrays work the same, only that they use * instead of &.

sth
  • 222,467
  • 53
  • 283
  • 367
  • +1. Great. I wanted something like this. Now please pass and return other types as well. My question has several types. Also explain the rules! – Nawaz Mar 22 '11 at 23:14
  • The last example is used in a common snippet to obtain the size of an array as a static constant: `template char (&size_detail( T (&)[N] ))[N]; #define sizeof_array( a ) sizeof( size_detail(a) )` – David Rodríguez - dribeas Mar 23 '11 at 00:00
  • 1
    Also: noexcept and const (for methods) still goes after the argments. E.g. const noexept method `foo` that returns a reference to an int array of size 10 and takes a single char argument is declared as `int (&foo(char) const noexcept)[10];`. At that point, its probably better to use typedefs or trailing returns. – Artyer Aug 30 '18 at 08:40
  • How do we specify such a function is a `const` member function? – Aykhan Hagverdili Mar 27 '19 at 13:22
  • 1
    @Ayxan: See Artyer's comment – sth Mar 27 '19 at 14:36
12

With C++11's trailing return type syntax, you can also write:

auto foo () -> int (&)[3]
{
    static int some_array[3]; // doesn't have to be declared here
    return some_array; // return a reference to the array.
}
Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • 2
    Which returns a reference to an int array of three elements. – Thomas Eding Sep 30 '16 at 17:31
  • Ooh wow this is a really neat feature. https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/introduction_to_the_c_11_feature_trailing_return_types?lang=en – Andrew Oct 01 '16 at 01:35
9

You cannot return an array from a function.

8.3.5/6:

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.

EDIT: You'll love the syntax:

int (&bar()) [5] {
  static int x[5];
  return x;
}


int (* & bar()) [6][10] {
    static int x[6][10];
    static int (*y)[6][10] = &x;
    return y;
}
// Note - this returns a reference to a pointer to a 2d array, not exactly what you wanted.
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
Erik
  • 88,732
  • 13
  • 198
  • 189
3

As Erik mentioned, you can't return an array from a function. You can return a pointer or a reference, although the syntax is quite hairy:

// foo returns a pointer to an array 10 of int
int (*foo(float arg1, char arg2))[10] { ... }

// bar returns a reference to an array 10 of int
int (&foo(float arg1, char arg2))[10] { ... }

I'd strongly recommend making a typedef for the array type:

// IntArray10 is an alias for "array 10 of int"
typedef int IntArray10[10];

// Equivalent to the preceding definitions
IntArray10 *foo(float arg1, char arg2) { ... }
IntArray10 &bar(float arg1, char arg2) { ... }
Community
  • 1
  • 1
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
1

Supplemental to the fine answer by sth, here is how to declare a class with a constant method returning an array reference:

class MyClass
{
public:
    const int (&getIntArray() const)[10];
};
0

This is tagged C++, so I'm going to suggest that the way to return an array in C++ is to return a std::vector and not try any trickery with C-arrays (which should be used only in carefully selected scenarios in C++ code).

As other answers noted, you can't return C-arrays from functions.

Mark B
  • 95,107
  • 10
  • 109
  • 188