Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Wskaźniki

Ostatnio zmodyfikowano 2018-08-15 23:42
Autor Wiadomość
Gowers
Temat założony przez niniejszego użytkownika
Wskaźniki
» 2018-08-15 17:43:00
Witam, mam kilka pytań dotyczących wskaźników:
kod z lekcji 44 operatory new i delete:
C/C++
int main()
{
    int * tablica = nullptr, rozmiar = 0;
    std::cout << "Podawaj liczby, 0 konczy wczytywanie.\n";
   
    while( true )
    {
        int liczba;
        std::cin >> liczba;
       
        if( liczba == 0 )
             break;
       
        // Brakuje miejsca, utwórz większą tablicę
        int * nowa = new int[ rozmiar + 1 ];
       
        // Skopiuj dane
        for( int i = 0; i < rozmiar; ++i )
             nowa[ i ] = tablica[ i ];
       
        // Dodaj nową wartość
        nowa[ rozmiar ] = liczba;
       
        // Usuń starą tablicę
        delete[] tablica;
       
        // Zakutalizuj zmienne
        tablica = nowa;
        rozmiar++;
    }
   
    std::cout << "Te same liczby, ale odwrotnie!\n";
   
    for( int i = rozmiar - 1; i >= 0; --i )
         std::cout << tablica[ i ] << ' ';
   
    delete[] tablica;
}

1. Jeśli w pętli tworzymy tablicę "nowa" o rozmiarze "rozmiar + 1", a potem wskaźnik "tablica" ustawiamy na początek tablicy "nowa", to po wyjściu z pętli normalnie dalej mamy dostęp do tej tablicy przez zmienną "tablica"? Zmienna nowa jest kasowana po wyjściu z pętli, ale te stworzone elementy zostają? Nie rozumiem tego trochę.
2. Tworzymy zwykłą zmienną wskaźnikową "tablica" i po ustawieniu jej na adres nowa, normalnie możemy na niej operować jak na tablicy? Wskaźnik sam "wie", że został ustawiony na pierwszy element tablicy i dlatego można tak działać?

C/C++
if( 1 )
{
    int * tab = new int[ 5 ];
}

3. W sumie to to samo co w pierwszym pytaniu. Czy w takim przypadku będzie wyciek pamięci? Po wyjściu z ifa zmienna tab zostanie usunięta, ale przydzielone elementy zostaną? Czy co się stanie? Należy tutaj też użyć
delete[] tab
?

C/C++
int main()
{
    int * tab = new int[ 5 ];
    return 0;
}

4. W powyższym przypadku, gdy mamy dynamicznie przydzieloną tablicę, która ma istnieć przez cały czas trwania programu to musimy ją potem zwolnić? Czy po zakończeniu programu, samo się wszystko zwolni? Czy jednak dla samego nawyku wypada użyć operatora delete?

P-172112
Rashmistrz
» 2018-08-15 18:57:07
Wow… Nawet nie zauważyłem, że wyszły nowe części kursu… anyway…

Zmienna nowa jest kasowana po wyjściu z pętli,
ale te stworzone elementy zostają?
1.Na tym polega dynamiczna alokacja,
każdy ma dostęp do pamięci kto ma wskaźnik.
Zmienna wskaźnikowa i jej wartość zostaje zniszczona,
jednakże pamięć dynamiczna wymaga użycia delete.

[...], normalnie możemy na niej operować jak na tablicy?
2.Przypisujesz do zmiennej ten sam typ,
więc możesz go wykorzystać tak samo.

Pamiętaj, że new int i new int[],
zwracają to samo, tylko do każdego inne delete.

Dla wskaźnika możesz od razu go wyłuskać: *tab
bądź użyć na nim offsetu: tab[offset]
Widziałem też taką śmieszność: *(tab+offset)

Czy w takim przypadku będzie wyciek pamięci?
3.Kasowany jest sam wskaźnik,
a nie pamięć na którą wskazuje.

Pamięć dynamiczna musi mieć właściciela,
który zadba o kasację pamięci, po jej użyciu.

Wyciek pamięci następuje,
gdy pamięć traci właściciela,
a nie zostaje przed tym zwolniona.

W przypadku, gdy właścicieli jest wielu,
bądź referujących więcej niż jeden,
należy się ustrzec przedwczesnego zwolnienia,
jak i także samego wycieku pamięci...

Wskaźniki inteligentne z następnych lekcji pomogą w tej sprawie.

Czy po zakończeniu programu, samo się wszystko zwolni?
> samo się wszystko zwolni
> dla samego nawyku wypada użyć operatora delete

Dla jasności czytających Twój kod w przyszłości,
wliczając w to Ciebie, wypadało by... ;)
P-172114
pekfos
» 2018-08-15 19:00:07
Wskaźnik sam "wie", że został ustawiony na pierwszy element tablicy i dlatego można tak działać?
Wskaźnik niczego nie wie. W rozdziale o wskaźnikach masz napisane że
  • Wskaźnik przechowuje adres w pamięci,
  • Operator [] to dereferencja adresu z offsetem.
Możesz używać [] nawet, jeśli nie wskazujesz na tablicę (wtedy tylko indeks zero jest poprawny) i nawet jeśli nie wskazujesz na pierwszy element w tablicy.

Czy w takim przypadku będzie wyciek pamięci? Po wyjściu z ifa zmienna tab zostanie usunięta, ale przydzielone elementy zostaną? Czy co się stanie?
Eh.
Każda zaalokowana pamięć powinna zostać zwolniona. Jeśli program w jakimś przypadku nie zwalnia pamięci, mamy wówczas do czynienia z wyciekiem pamięci (memory leak). Niezwalnianie pamięci może doprowadzić do wyczerpania zasobów komputera, a wtedy będzie problem. Nie da się stwierdzić, czy jakaś pamięć jest nieużywana i potrzebna, czy nieużywana i niepotrzebna, bo jakiś niezdarny programista zgubił jej adres.
Nawet było na czerwono.

W powyższym przypadku, gdy mamy dynamicznie przydzieloną tablicę, która ma istnieć przez cały czas trwania programu to musimy ją potem zwolnić? Czy po zakończeniu programu, samo się wszystko zwolni?
Cała pamięć zostanie zwolniona po zakończeniu programu. Tak samo jak cały bałagan który zrobisz u kogoś "sam się posprząta", tylko potem niekoniecznie będziesz mile widzianym gościem.
P-172115
Gowers
Temat założony przez niniejszego użytkownika
» 2018-08-15 23:42:58
Dziękuję za odpowiedzi
P-172124
« 1 »
  Strona 1 z 1