Przekazywanie tablicy struktur przez odwołanie w C ++


Więc nadal jestem całkiem nowy w programowaniu/C ++ i wciąż próbuję zawinąć głowę wokół wskaźników, przeszłych odniesień i wszystkiego innego. Program, który teraz próbuję zrozumieć, musi przekazać tablicę struktur do innej funkcji. Zrobiłem to, po prostu przekazując tablicę właśnie tam. Wydaje się, że wszystko działa dobrze. Martwi mnie jednak to, że uważam, że przekazuję to według wartości i rozumiem, że lepiej jest przekazywać struktury przez odniesienie, aby nie tworzyć kopii struktury za każdym razem ...
W każdym razie, oto podstawowy przykład tego, co robię:
struct GoldenHelmet {
int foo;
string bar;
};void pass (GoldenHelmet ofMambrino[], int size);int main () {
GoldenHelmet ofMambrino[10];
int size = sizeof(ofMambrino)/sizeof(ofMambrino[0]);
ofMambrino[1].foo = 1;
pass(ofMambrino, size);
cout << ofMambrino[2].foo << endl;
return 0;
}void pass (GoldenHelmet ofMambrino[], int size) {
ofMambrino[2].foo = 100;
ofMambrino[2].bar = "Blargh";
}

Jak rozumiem, to działa, ponieważ tablice są już wskaźnikami, prawda? Ale sposób, w jaki to skonfigurowałem, czy nadal przekazuję kopię struktury i wszystkiego innego do funkcji pass ()? Próbowałem przekazać to przez odniesienie, ale wydaje się, że nie chce działać tak, jak próbowałem.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

W C ++ sposób jest następujący:
#include <array>typedef std::array<GoldenHelmet, 10> Helmets;void pass(Helmets &);int main()
{
Helmets h;
h[1].foo = 1;
pass(h);
//...
}void pass(Helmets & h)
{
h[2].foo = 100;
// ...
}

Rzeczywiście, przekazujemy tablicę przez odniesienie.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ta składnia:
void pass (GoldenHelmet ofMambrino[], int size)

to właściwie dość zagmatwane. Ponieważ nie przekazujesz tablicy, przekazujesz wskaźnik. Ale to nie to samo, nie dajcie się zmylić. Ta dziwność dotyczy tylko parametrów funkcji. Powyższe jest dokładnie takie samo:
void pass (GoldenHelmet * ofMambrino, int size)

Przekazanie tablicy według wartości nie jest naprawdę możliwe, chyba że jest to podobiekt innego obiektu. Możesz przekazać je przez odniesienie, chociaż musisz podać rozmiar, ale możesz to zrobić za pomocą szablonu:
template<int N>
void pass (GoldenHelmet (&ofMambrino)[N])
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wszystko to jest możliwe, ale żaden z nich nie przechodzi przez wartość. Po prostu pomyśl o
ofMambrino
jako adresie początku tablicy i to właśnie przekazujesz.
void pass (GoldenHelmet ofMambrino[], int size)
void pass (GoldenHelmet ofMambrino[10], int size)
void pass (GoldenHelmet *ofMambrino, int size)
void pass (GoldenHelmet (&ofMambrino)[10], int size)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Tablice są reprezentowane i przekazywane jako wskaźniki, więc niczego tutaj nie kopiujesz. Wręcz przeciwnie, gdybyś mijał

jeden
struct
, zostanie przekazana przez wartość.
Poniżej znajduje się fragment kodu ilustrujący ten ostatni punkt:
void passByVal (GoldenHelmet ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}void passByRef (GoldenHelmet& ofMambrino) {
ofMambrino.foo = 100;
ofMambrino.bar = "Blargh";
}int main() {
GoldenHelmet h;
passByVal(h);// h does not change
passByRef(h);// fields of h get assigned in the call
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Po pierwsze, tablica nie jest wskaźnikami. Nazywamy to wskaźnikiem na liście argumentów, ponieważ kiedy używamy
int x[ ]

x jest właściwie wskaźnikiem do stałej, który wskazuje na początek tablicy. A kiedy przekazujesz to do funkcji, wysyłasz adres pamięci, która jest początkiem tablicy. Dlatego, kiedy wprowadzasz zmiany w swojej funkcji, w rzeczywistości wprowadzasz zmiany w adresie swojej zmiennej w sekcji wywołującej. W rzeczywistości jest to symulowane połączenie przez odniesienie, a nie połączenie przez odniesienie. Ale efekt jest taki sam, jak wywołanie przez odniesienie, ponieważ pracujesz z lokalizacjami pamięci. Z tego powodu, kiedy wysyłasz tablicę swojej struktury, przekazujesz rzeczywisty adres swojej tablicy struktur. Dlatego zmieniając wartość tego, w rzeczywistości zmieniasz swoje struktury.
Aby użyć wywołania przez odniesienie, jedną rzeczą, którą musisz zrobić, jest zdefiniowanie prototypu funkcji w ten sposób
void f(int &param)

a kiedy wywoływana jest funkcja, to samo dzieje się z innymi.
Zreasumowanie:
int main()
{
int x;// simulated call by reference that use adress of variable,
// lets say adress of x is 19ff
f(&x);// actually you send 19ff f(x);// call by reference that use reference of variable}// simulated call by reference
void f(const int *y)
{
// when you use like *y=10, you are writing on memory area 19ff, you actually
// change memory area that is belong to x in the main}// call by reference
void f(const int &y)
{
}

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się