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

Dynamiczne przydzielanie pamięci - operator new [problem ze zrozumieniem]

Ostatnio zmodyfikowano 2015-05-12 11:26
Autor Wiadomość
Dreux
Temat założony przez niniejszego użytkownika
Dynamiczne przydzielanie pamięci - operator new [problem ze zrozumieniem]
» 2015-05-09 18:35:52
A więc zupełnie nie rozumiem celu korzystania z operatora new. Z tego co wiem, posługujemy się nim wówczas, gdy chcemy utworzyć zmienną lub tablicę elementów, której wartości/wielkości nie znamy lub dla oszukania systemu (nie można utworzyć tak wielkiej tablicy, a więc wykorzystujemy operator new, nie zdradzając ile ta wielkość ma wynosić). Lecz skoro nie znamy początkowej wartości, dlaczego mamy informować program o liczbie elementów tablicy? Po co pisać *wsk = new int [10], skoro równie dobrze można napisać int tablica[10]? Generalnie trudno mi się obejść z całym działem, więc prosiłabym o dokładne wytłumaczenie, bo może diabeł tkwi w szczegółach (np. źle rozumiem pojęcie "wielkość", "początkowa wartość").
P-131948
pekfos
» 2015-05-09 18:39:18
lub dla oszukania systemu (nie można utworzyć tak wielkiej tablicy, a więc wykorzystujemy operator new, nie zdradzając ile ta wielkość ma wynosić).
Ale bzdura.

Po co pisać *wsk = new int [10], skoro równie dobrze można napisać int tablica[10]?
Nie możesz napisać int tablica[zmienna].
P-131949
Quirinnos
» 2015-05-09 19:13:31
Materiałów o tym jest sporo. Poczytaj o alokacji pamięci statycznej, dynamicznej. Stercie, stosie (jako obszarze pamięci).
Ogólnie gdy dajesz statycznie, np (int tab[10]), no to masz pamięć zarezerwowaną na te 10 int'ów. Czyli kompilator zapewnia, że gdzieś w pamięci (w tym przypadku w logicznej części pamięci, zwanej stosem) wydzieli sobie 40 bajtów i nie będzie po tej pamięci mazał czym innym. Kompilator C++ nie pilnuje tego czy ty przekroczysz ten przedział. Nie pamięta na ile elementów została zarezerwowana pamięć, on tylko gwarantuje, że tyle a tyle pamięci będzie trzymał dla ciebie :D. Jednak pamięć stosu jest ograniczona, z góry narzucona przez kompilator i dlatego nie możliwe jest stworzenie dużej tablicy statycznie, bo przekracza ona dostępną pamięć. W tedy właśnie potrzeba operatora new. Który alokuje pamięć na stercie. Zasada ta sama. *wsk = new int [10], daje Ci wskaźnik na początek tablicy i gwarancję, że ta pamięć będzie trzymana dla ciebie.
Co do tablic ze "zmienną" wielkością:
http://gynvael.coldwind.pl/​?id=300
P-131950
Dreux
Temat założony przez niniejszego użytkownika
» 2015-05-09 23:55:18
Czyli jeśli dobrze zrozumiałam to:
a)pamięć statyczna nadawana wraz z tworzeniem zmiennej (czyt.stała przypisana do niej wartość), a pamięć dynamiczna - zmieniająca się na bieżąco w zależności od tego, ile potrzebujesz;
b)w stercie przechowuje się zmienne dynamiczne, w stosie coś w rodzaju "pamięci podręcznej";
c)choć tworzenie tablic o wielkości nieznanej zmiennej jest niekiedy możliwe (jak u mnie w kompilatorze) to niezalecane, ponieważ nie kompatybilne z niektórymi kompilatorami (czyt.program może u kogoś innego nie działać);
d)przy tworzeniu tablic o większej liczbie elementów może nie starczyć przydzielonej pamięci.
Tylko wciąż nie zrozumiałam czemu służy określanie wielkości tablicy. Skoro nie wiemy ile elementów i tworzone będą na bieżąco to nie wiemy. Czy może to kwestia tego, że o ile kompilator może zaprotestować przy utworzeniu int tablica[900000000] to przy *wsk = new int [9000000000] nie zaprotestuje?
Jeśli coś źle napisałam, proszę mnie poprawić :)

P-131964
carlosmay
» 2015-05-10 02:21:40
np. źle rozumiem pojęcie "wielkość"
wielkość tablicy, czyli rozmiar w nawiasie kwadratowym.
Statyczna tablica musi mieć tam wartość stałą np. np.
C/C++
const int rozmiar = 10;
int tab[ rozmiar ];
lub
int tab[ 10 ];
a dynamicznie nie musi być to wartość stała
C/C++
int rozmiar;
cout << "Podaj wielkosc tablicy: "; // uruchamiamy program i dopiero wtedy pyta ile elementow ma miec tablic (moze miec 10, 100, 1000 itd.)
cin >> rozmiar; // wczytujemy rozmiar
int * wtab = new int[ rozmiar ]; // tutaj deklarujemy wskaznik *wtab na pierwszy element tablicy o zadanym rozmiarze (np. 10, 100, 1000 itd.)
Są różnice w wydajności programów z alokacją dynamiczną i statyczną i tutaj programer musi zdecydować czego potrzebuje.

Służy temu, że piszesz nap bazę informacji i nie wiesz ile dokładnie ma ich być.
Deklarujesz nieduża tablice dynamicznie i jej używasz.
Teraz jest sytuacja, że zapełniasz ostatni element tablicy, a potrzebujesz jeszcze kilka nowych,
więc warunkujesz w programie, "jeśli ostatni element jest zapisany dołóż do programu następne
elementy tablicy.
Wtedy robisz tak:
1. zamiast tego
int * wsk = new int[ 10 ];
 deklarujesz
* wsk = new int[ rozmiar ]
gdzie rozmiar jest zmienna całkowita, ale juz nie musi być
const int rozmiar = 10;
.
2. zmieniasz wartość zmiennej "rozmiar" i program w czasie wykonywania alokuje nową pamieć
na tyle elementów ile właśnie potrzebujesz.
3. Następnie kopiuje elementy tablicy ze starego miejsca na nowo utworzone.

Można zrobić to tak:
C/C++
int * zwiekszTab( int * w_wartosci, int * rozmiar )
{
    * rozmiar *= 2;
    int * w_nowe_wartosci = new int[ * rozmiar ];
    for( int i = 0; i < * rozmiar; ++i )
    {
        w_nowe_wartosci[ i ] = w_wartosci[ i ];
    }
   
    delete[] w_wartosci;
    return w_nowe_wartosci;
}
jest to fragment funkcji zajmujący  się powiększaniem tablicy na bieżąco.
Krok 1. przekazujemy zapełnioną tablice i jej rozmiar.
Krok 2. podwajamy wartość zmiennej "rozmiar".
Krok 3. alokujemy nową dynamiczną tablice i do niej kopiujemy ze starej tablicy.
Krok 4. usuwamy starą tablicę w przykładzie "w wartości" i zwracamy nową tablicę w miejsce skąd była wywołana.
Krok 5. cieszymy się, że mamy nową większą tablicę póki znów się nie zapełni, wtedy znów wywołujemy funkcję zwiększająca tablicę itd.

Daje nam to tyle, że można w miarę upływu czasu, powiększać zasoby nie zajmując niepotrzebnie miejsca.
Statycznie musisz przydzielić stałą ilość pamięci (w trakcie kompilowania) i się jej kurczowo trzymać, dynamiczna daje swobodę
zmiany wielkości w trakcie działania programu. Ustawiasz warunek, który wykrywa, że tablica jest pełna i ją np. podwaja.[/code]
P-131965
Piastlis
» 2015-05-10 11:22:15
Sposób wykorzystania tego mechanizmu zależy tylko od wyobraźni.Niewątpliwą zaletą jest to że wszystkie elementy nie muszą istnieć jednocześnie.Lepiej wykorzystuje się pamięć.Przepisywanie      wartości też nie jest konieczne.Wystarczy stablicować wskaźniki. Odwołanie wygląda tak:

tablica[n/100][n % 100]

Początkowo wszystkie elementy tablica mogą wskazywać na obiekt z samymi 0.   
P-131981
pekfos
» 2015-05-10 11:48:44
Tylko wciąż nie zrozumiałam czemu służy określanie wielkości tablicy. Skoro nie wiemy ile elementów i tworzone będą na bieżąco to nie wiemy.
W pamięci dynamicznej nic nie jest tworzone 'na bieżąco'. Podany rozmiar określa, ile elementów ma zostać utworzonych i nie możesz tej wartości przekroczyć, operując na tej tablicy.

Można zrobić to tak:
Ten kod jest błędny.
P-131982
Piastlis
» 2015-05-10 11:59:45
tablica[n/100][n % 100]


To idea nie kod.(n/100) wskaźnik na tablicę i z niego (n % 100) element.
P-131983
« 1 » 2
  Strona 1 z 2 Następna strona