Przekazywanie tablicy przez referencję

184

Jak działa przekazywanie statycznie przydzielonej tablicy przez referencję?

void foo(int (&myArray)[100])
{
}

int main()
{
    int a[100];
    foo(a);
}

Czy (&myArray)[100]ma jakieś znaczenie lub po prostu składnia do przekazania dowolnej tablicy przez odwołanie? Nie rozumiem osobnych nawiasów, po których następują duże nawiasy. Dzięki.

John DB
źródło
Czy istnieje jakikolwiek związek wartości z wartości do wartości z parametrami funkcji?
John DB

Odpowiedzi:

228

Jest to składnia odwołań do tablicy - musisz użyć, (&array)aby wyjaśnić kompilatorowi, że chcesz odwoływać się do tablicy, zamiast (nieprawidłowej) tablicy odwołań int & array[100];.

EDYCJA: Trochę wyjaśnień.

void foo(int * x);
void foo(int x[100]);
void foo(int x[]);

Te trzy są różnymi sposobami zadeklarowania tej samej funkcji. Wszystkie są traktowane jako przyjmujące int *parametry, możesz przekazać do nich dowolną tablicę rozmiarów.

void foo(int (&x)[100]);

Akceptuje to tylko tablice 100 liczb całkowitych. Możesz bezpiecznie używać sizeofnax

void foo(int & x[100]); // error

Jest to analizowane jako „tablica referencji” - co jest niezgodne z prawem.

Erik
źródło
Dlaczego nie możemy mieć na przykład szeregu referencji int a, b, c; int arr[3] = {a, b, c};?
Vorac
4
Aha, dowiedziałem się dlaczego .
Vorac
2
Czy ktoś mógłby wyjaśnić, dlaczego void foo(int & x[100]);jest analizowany jako „tablica referencji”? Czy to dlatego, że zasada „od prawej do lewej”? Jeśli tak, wydaje się, że nie jest to zgodne z tym, jak void foo(int (&x)[100]);jest analizowane jako „odwołanie do tablicy”. Z góry dziękuję.
zl9394
3
Nie jest od prawej do lewej, jest wywrócony na lewą stronę, a [] wiąże się mocniej niż &.
philipxy
48

To tylko wymagana składnia:

void Func(int (&myArray)[100])

^ Przekaż tablicę 100 intprzez odniesienie nazwa parametru to myArray;

void Func(int* myArray)

^ Przekaż tablicę. Tablica rozpada się na wskaźnik. W ten sposób tracisz informacje o rozmiarze.

void Func(int (*myFunc)(double))

^ Przekaż wskaźnik funkcji. Funkcja zwraca an inti przyjmuje a double. Nazwa parametru to myFunc.

Martin York
źródło
Jak przekazujemy tablicę o zmiennej wielkości jako odniesienie?
Shivam Arora
@ShivamArora Szablon tworzysz szablon i ustawiasz rozmiar jako parametr szablonu.
Martin York
24

To jest składnia. W argumentach funkcji konieczny jest int (&myArray)[100]nawias, który &myArrayzawiera. jeśli ich nie użyjesz, zdasz array of referencesi to dlatego, że subscript operator []ma wyższy priorytet niż & operator.

Na przykład int &myArray[100] // array of references

Tak więc, używając type construction (), powiesz kompilatorowi, że chcesz odwołać się do tablicy 100 liczb całkowitych.

Na przykład int (&myArray)[100] // reference of an array of 100 ints

CPX
źródło
„jeśli ich nie użyjesz, zdasz array of references” - co oczywiście nie może istnieć, więc otrzymasz błąd kompilacji. Zabawne jest dla mnie, że reguły pierwszeństwa operatorów nalegają, aby tak się stało domyślnie.
underscore_d
Czy jest jeszcze tutorial na temat budowy typów ()?
Chifter Shifter,
Dzięki, potrzebowałem wyjaśnienia, które zawierało powód pierwszeństwa operatora, co daje sens, dlaczego należy to zrobić w ten sposób.
cram2208
4

Tablice są domyślnie przekazywane przez wskaźniki. Możesz spróbować zmodyfikować tablicę w wywołaniu funkcji w celu lepszego zrozumienia.

Eduardo A. Fernández Díaz
źródło
2
Tablice nie mogą być przekazywane przez wartość. Jeśli funkcja otrzyma wskaźnik, tablica rozpada się na wskaźnik do pierwszego elementu. Nie jestem pewien, co próbujesz tu powiedzieć.
Ulrich Eckhardt,
@UlrichEckhardt Próbuję powiedzieć, że „tablice nie mogą być przekazywane przez wartość”, jak powiedziałeś wcześniej, są domyślnie przekazywane przez odniesienie
Eduardo A. Fernández Díaz
8
Tablice nie są przekazywane ani przez wartość, ani przez odwołanie. Są przekazywane przez wskaźniki. Jeśli tablice są domyślnie przekazywane przez referencję, nie będzie problemu z użyciem na nich sizeof. Ale tak nie jest. Tablice rozpadają się na wskaźniki po przekazaniu do funkcji.
user3437460
2
Tablice mogą być przekazywane przez odniesienie LUB przez degradację do wskaźnika. Na przykład użycie char arr[1]; foo(char arr[]).arr obniża się do wskaźnika; podczas używania char arr[1]; foo(char (&arr)[1])arr jest przekazywany jako odniesienie. Warto zauważyć, że poprzednia forma jest często uważana za źle sformułowaną, ponieważ wymiar zostaje utracony.
zl9394
Re: „Tablice są ... przekazywane przez wskaźniki”. Ten opis w najlepszym razie brzmi niekonwencjonalnie i może być mylący dla początkujących. Nazwa od zmiennej tablicowej, jest poprawnym wyrażeniem, którego wartość jest wskaźnikiem The pierwszy element tablicy. Jeśli masz jakąś funkcję foo(T* t)i masz tablicę, T a[N];wtedy, gdy piszesz foo(a);, myślę, że bardziej poprawne byłoby powiedzenie, że przekazujesz wskaźnik, a nie tablicę, i przekazujesz wskaźnik według wartości.
Solomon Slow
1

Następujące tworzy ogólną funkcję, przyjmując tablicę dowolnego rozmiaru i dowolnego typu przez odniesienie:

template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
   // do stuff
}

baw się kodem.

Użytkownik12547645
źródło