Общие правила передачи/возврата ссылки на массив (не указатель) на/из функции?
Мы можем передать ссылку массива на такую функцию, как:
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]
не является массивом, это указатель на массив.
Да. Но одно измерение известно во время компиляции! Как мы можем передать эту информацию, которая известна во время компиляции, функции?
Ответы
Ответ 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 (¶m)[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-массивы из функций.