Czy można przesłać tablice do funkcji przez parametr referencyjny?

0

Mam kolejne pytanie dotyczące referencji. xd
Czy można przesyłać tablice z funkcji main do innej funkcji przez parametr referencyjny? Uczę się C++ z książki Praty i na 364 stronie jest opisane, kiedy korzystać z referencji jako parametrów, a kiedy lepiej używać wskaźników i jest napisane, że "jeżeli obiekt danych jest tablicą, to nie mamy wyboru i trzeba użyć wskaźnika". Tyle że szukałem na necie info na ten temat i udało mi się stworzyć funkcję, które pobierają tablicę przez parametr referencyjny. Napisałem dla przykładu dwa programy: pierwszy po prostu wyświetla zawartość tablicy i ją modyfikuje. W drugim wyświetlana jest struktura i potem też w prosty sposób modyfikowana.

Program 1:

#include <iostream>
#include <string>

#define n 10

using namespace std;

void wyswietl(const int (&t)[n], int e); void modyfikuj(int (&t)[n], int e); 
int main() 
{
    int tab[n];
    int (&rf)[n] = tab;

    cout<<"Zawartosc tablicy tab wyswietlona przez referencje rf:\n"<<endl;
    int i=0;

    while(i<n) //w tej petli akurat wyswietlilem elementy przez referencje rf, ale do funkcji przeslalem juz sama tablice tab
    {
        rf[i] = i+1;
        cout<<"Element "<<i+1<<": "<<rf[i]<<endl;
        i++;

    }

    cout<<"\nTeraz ponownie wyswietle elementy, ale za pomoca funkcji z parametrem referencyjnym.\n"<<endl;
    wyswietl(tab,n);
    cout<<"\nTeraz zmodyfikuje dane za pomoca funkcji, wymnazajac kazdy element przez siebie"<<endl;
    modyfikuj(tab, n);
    cout<<"\nTeraz ponownie wyswietle elementy, za pomoca funkcji z parametrem referencyjnym.\n"<<endl;
    wyswietl(tab,n);

    return 0;
}

void modyfikuj(int (&t)[n], int e)
{
    int i=0;
    while(i<e)
    {
        t[i] *= t[i];
        i++;
    }
}

void wyswietl(const int (&t)[n], int e)
{
    int i=0;
    while(i<e)
    {
        cout<<"Element "<<i+1<<": "<<t[i]<<endl;
        i++;
    }
}

Program 2:

#include <iostream>
#include <string>

#define n 3

using namespace std;

struct person
{
    string imie;
    float wzrost;
    int wiek;
};

void pokaz_r(person (&rf)[n]); void modyfikuj_r(person (&rf)[n]);

int main()
{
    person osoba[n];

    cout<<"Podaj dane 3 osob."<<endl;

    int i=0;
    while(i<n)
    {
        cout<<"\nPodaj imie osoby "<<i+1<<": "<<endl;
        getline(cin, osoba[i].imie);
        cout<<"Podaj wzrost osoby "<<i+1<<": "<<endl;
        cin>>osoba[i].wzrost;
        cout<<"Podaj wiek w latach osoby "<<i+1<<": "<<endl;
        cin>>osoba[i].wiek; cin.get();
        i++;
    }
    cout<<"Teraz wyswietle dane przez funkcje z parametrem referencyjnym"<<endl;
    pokaz_r(osoba);
    cout<<"Teraz zwieksze wszystkie dane o 1, a do imienia dopisze litere 'A'"<<endl;
    modyfikuj_r(osoba);
    cout<<"Teraz ponownie wyswietle dane przez funkcje\n"<<endl;
    pokaz_r(osoba);

}

void modyfikuj_r(person (&rf)[n])
{
    int i=0;

    while(i<n)
    {
        rf[i].imie += 'A';
        rf[i].wzrost++;
        rf[i].wiek++;
        i++;
    }
}

void pokaz_r(person (&rf)[n] )
{
    int i=0;

    while(i<n)
    {
        cout<<"Osoba "<<i+1<<"."<<endl;
        cout<<"Imie: "<<rf[i].imie<<endl;
        cout<<"Wzrost: "<<rf[i].wzrost<<endl;
        cout<<"Wiek: "<<rf[i].wiek<<endl<<endl;
        i++;
    }

}

Obywda programy działają, czyli mam rozumieć, że można przesyłać tablice przez parametr referencyjny do funkcji? Tylko dlaczego w książce jest napisane, że trzeba użyć wskaźników? I chciałbym się dopytać, czy zrobiłem to w dobry sposób, zwłaszcza o poniższy zapis:

 int tab[n]; //stworzenei tablicy
 int (&rf)[n] = tab; //stworzenie referencji i przypisanie jej tablicy tab

 void modyfikuj(int (&t)[n], int e) //wygląd parametrów w funkcji

I ostatnie pytanie: czy można stworzyć referencje do tablicy dynamicznej, którą stworzyliśmy za pomocą "new" albo klasy "vector"? I czy można taką tablicę też przekazać do funkcji przez parametr referencyjny?

2

Można mieć referencje do tablicy. Dobrze zrobiłeś. Można mieć referencję do tablicy dynamicznej, ale to będzie referencja do wskaźnika, bo wielkość tablicy jest enkodowana w typie, a więc musi być znana w czasie kompilacji.

Dodatkowa lektura: https://dev.krzaq.cc/post/readable-function-pointers/ (tl;dr: using potrafi uprzyjemnić pracę z takimi typami, jeśli jesteś zmuszony ich użyć)

1

Z poprzedniej lekcji wiesz, że referencje są de facto wskaźnikami - więc jak sam odkryłeś możesz użyć referencji do przesłania tablicy do funkcji.

0
kq napisał(a):

Można mieć referencje do tablicy. Dobrze zrobiłeś. Można mieć referencję do tablicy dynamicznej, ale to będzie referencja do wskaźnika, bo wielkość tablicy jest enkodowana w typie, a więc musi być znana w czasie kompilacji.

Dodatkowa lektura: https://dev.krzaq.cc/post/readable-function-pointers/ (tl;dr: using potrafi uprzyjemnić pracę z takimi typami, jeśli jesteś zmuszony ich użyć)

Sorry, ale nie znam angielskiego, więc z tej lektury chyba nic nie będzie. xd Napisałeś, że referencja do tablicy dynamicznej może być, ale jej rozmiar musi być znany w trakcie kompilacji programu, czyli taki kod:

    int m=0;
    cout<<"Podaj, jak duza tablice chcesz zrobic: "<<endl;
    cin>>m;

    int * tab = new int [m];
    int (&rf)[n] = *tab;

Nie ma prawa działać (i rzeczywiście, nie mogę tego skompilować), mimo że zrobiłem to analogicznie, jak w przypadku stałej tablicy?

1

Tak. Typ tablicy to T[n], a typ tego co zwraca new to T*, więc nie możesz tego przypisać do T(&)[n] i tyle.

0

Wszystko rozumiem. Wielkie dzięki Panowie! Z Waszymi radami nauka programowania jest dużo łatwiejsza. :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1