Общие правила передачи / возврата ссылки на массив (не указатель) в / из функции? - PullRequest
33 голосов
/ 23 марта 2011

Мы можем передать ссылку на массив функции, подобной:

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

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

Или даже лучше, мы можем написать шаблон функции:

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

Теперь мой вопрос: как вернуть ссылку на массив из функции?

Я хочу вернуть массив следующих типов из функции:

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

где M и N известны во время компиляции!

Каковы общие правила для передачи и возврата ссылки во время компиляции массива в функцию и из функции? Как мы можем передать ссылку на массив типа int (*a)[M][N] в функцию?

EDIT:

Адам прокомментировал: int (*a)[N] это не массив, это указатель на массив.

Да. Но одно измерение известно во время компиляции! Как мы можем передать эту информацию, которая известна во время компиляции, функции?

Ответы [ 6 ]

44 голосов
/ 23 марта 2011

Если вы хотите вернуть ссылку на массив из функции, объявление будет выглядеть следующим образом:

// an array
int global[10];

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

Объявление функции, возвращающей ссылку на массив, выглядит так же, как объявлениепеременной, которая является ссылкой на массив - только после того, как за именем функции следует (), который может содержать объявления параметров:

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

Такие объявления можно сделать намного более понятными с помощью typedef:

typedef int array_t[10];

array_t& f() {
   return global;
}

Если вы хотите, чтобы это действительно сбивало с толку, вы можете объявить функцию, которая принимает ссылку на массив и также возвращает такую ​​ссылку:

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

Указатели для массивов работают одинаково, только они используют * вместо &.

10 голосов
/ 07 августа 2014

С помощью синтаксиса завершающего возвращаемого типа в C ++ 11 вы также можете написать:

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.
}
9 голосов
/ 23 марта 2011

Вы не можете вернуть массив из функции.

8.3.5 / 6

Функции не должны иметь тип возврата типа массива или функции, хотя они могут иметь тип возвращаемого типа указатель или ссылка на такие вещи.

РЕДАКТИРОВАТЬ: Вам понравится синтаксис:

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.
3 голосов
/ 23 марта 2011

Как и Эрик упомянул , вы не можете вернуть массив из функции. Вы можете вернуть указатель или ссылку, хотя синтаксис довольно сложный:

// 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] { ... }

Я бы настоятельно рекомендовал сделать typedef для типа массива:

// 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) { ... }
1 голос
/ 27 января 2016

В дополнение к точному ответу по sth, вот как объявить класс с помощью константного метода, возвращающего ссылку на массив:

class MyClass
{
public:
    const int (&getIntArray() const)[10];
};
0 голосов
/ 23 марта 2011

Это тег C ++, поэтому я собираюсь предположить, что способ вернуть массив в C ++ - это вернуть std::vector и не пытаться использовать хитрости с C-массивами (которые следует использовать только в тщательно отобранных сценариях в коде C ++).

Как отмечалось в других ответах, вы не можете возвращать C-массивы из функций.

...