Подтвердить что ты не робот

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

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

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:

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

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

4b9b3361

Ответ 1

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

// 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;
}

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

Ответ 2

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

8.3.5/6:

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

EDIT: вам понравится синтаксис:

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

С синтаксисом типа возвращаемого типа возврата С++ 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.
}

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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