Zwracanie wskaznika przez funkcje

0
#include <iostream>
#include <fstream>
using namespace std;

struct Student {
string imie;
string nazwisko;
unsigned int nr_indeksu;
};

Student *wczytaj(ifstream &plik,int &lp)
{
    plik.open("a.txt",ios::in);
    if(!plik){
        cerr << 'Nie udalo sie otworzyc pliku ! ';
    }
    plik >> lp;
    Student *uczniowie = new Student[lp];
    for(int i = 0 ; i < lp ; i++)
    {
        plik >> uczniowie[i].imie;
        plik >> uczniowie[i].nazwisko;
        plik >> uczniowie[i].nr_indeksu;
    }
    return uczniowie;
}
int main()
{
    ifstream plik;
    int lp;
    Student *studenci = wczytaj(plik,lp);
return 0;

}

Czym to by sie roznilo od takiego zwrocenia wskaznika 
Student wczytaj(ifstream &plik,int &lp)
{
    plik.open("a.txt",ios::in);
    if(!plik){
        cerr << 'Nie udalo sie otworzyc pliku ! ';
    }
    plik >> lp;
    Student *uczniowie = new Student[lp];
    for(int i = 0 ; i < lp ; i++)
    {
        plik >> uczniowie[i].imie;
        plik >> uczniowie[i].nazwisko;
        plik >> uczniowie[i].nr_indeksu;
    }
    return *uczniowie; // wiem ze wtedy w mainie by nie dzialalo by przypisanie     Student *studenci = wczytaj(plik,lp);
} 

Czyli nie wiem czym sie to rozni i kiedy ktore stosowac zwrocenia wskaznika poprzez return i poprzez zwracanie wskaznika do okreslonego typu ?(jedynie wiem ze mam tak napisac jesli chce zwrocic dynamiczna tablice struktur)
Inne pytanie zapis Student *uczniowie = new Student[lp]; Jak mam to rozumiec ? ze jest to wskaznika na klase student i przydziela dynamicznie pamiec ?

3

Student wczytaj
Student* wczytaj

W obu funkcjach korzystasz z operatora new. Wiec w obu wypadkach bedzie wszystko dzialac. Tylko ze przy pierwszym nie tworzysz wskaznika. robisz na zasadzie

Student foo = wczytaj(...);

a w drugim

Student *foo = wczytaj(...);

roznica jest taka ze pozniej musisz ten obiekt zwolnic (za pomoca delete) w pierwszym wypadku nie bedziesz miec problemu bo masz wskaznik (delete dziala tylko ze wskaznikiem) w drugim wypadku bedziesz musial tworzyc wskaznik ktory pokazuje na zwrocony obiekt i dopiero ten wskaznik usuwac co jest nieporeczne.

Dodatkowo nie powinienes uzywac wskaznikow a smart pointerow i nie bawic sie w zwalnianie pamieci

tu masz dowod (usun delete i bedzie sie kompilowac, ale bedzie wtedy mem leak)

http://ideone.com/jhPLy5

odnosnie zwracanie nie wskaznika a obiekt. Jezeli tworzylbys tam obiekt lokalny (nie przez operator new) to wtedy jakbys zwrocil taki obiekt to bylby duzy blad. Poniewaz taki obiekt lokalny po wyjsciu z funkcji przestalby istniec.

Polecam poczytac o zasiegu zmiennych i ich cyklu zycia

4
return *uczniowie

Tutaj zwracasz pierwszy obiekt w "tablicy" uczniowie, czyli to jest równoważne

return uczniowie[0]
Student* uczniowie

Tworzy wskaźnik na obiekt typu Student, przy czym taki wskaźnik może również wskazywać na ciągły obszar pamięci wypełniony obiektami typu Student

new Student[lp]

Rezerwuje pamięć i tworzy lp obiektów typu Student, po czym zwraca wskaźnik na początek tego obszaru pamięci.

Po połączeniu

Student* uczniowie = new Student[lp]
  1. Tworzy wskaźnik
  2. Rezerwuje pamięć i tworzy obiekty
  3. Przypisuje adres tego obszaru pamięci do tego nowo utworzonego wskaźnika.
4

to jest wyciek pamięci! return *uczniowie; tworzy kopię obiektu, który stworzyłeś na stercie a do którego tracisz potem kontakt.
Ogólnie tego się tak nie robi.
Powinno być tak:

ostream & operator<<(ostream & strumien, const Student &student) {
      student.drukuj(strumien);
      return strumien;
}

istream & operator>>(istream & strumien, Student &student) {
      student.wczytaj(strumien);
      return strumien;
}

std::vector<std::shared_ptr<Student> > wczytajStudentow(istream &stream)
{
     std::vector<std::shared_ptr<Student> > wynik;
     auto pStudent = std::make_shared(new Student);
     while(stream>>*pStudent) {
           wynik.push_back(pStudent);
           pStudent = std::make_shared(new Student);
     }
     return wynik;
}
0

I na koniec w mainie zamknij plik...

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