- Samsung Galaxy S23 és S23+ - ami belül van, az számít igazán
- Samsung Galaxy Watch (Tizen és Wear OS) ingyenes számlapok, kupon kódok
- Samsung Galaxy S23 Ultra - non plus ultra
- Motorola Edge 50 Neo - az egyensúly gyengesége
- Xiaomi 13T és 13T Pro - nincs tétlenkedés
- VoLTE/VoWiFi
- Samsung Galaxy Watch7 - kötelező kör
- Milyen okostelefont vegyek?
- Google Pixel topik
- Telekom mobilszolgáltatások
Új hozzászólás Aktív témák
-
mgoogyi
senior tag
válasz
Teasüti #4155 üzenetére
Amit lehet a stacken jobb tartani(gyorsabb, nem kell delete), a nagy méretű adatot meg heap-en(van neki hely gazdagon).
A new+delete párra meg vannak osztályok, amikbe becsomagolva megkapod az eltakarítást.
std::vector a dinamikus tömbhöz, std::unique_ptr, std::auto_ptr egyéb mutatóhoz.
Ezek az osztályok a delete-et úgy oldják meg, hogy a destruktorukban meghívódik az általuk tárolt pointerre a delete.
És ezeket a pointer "wrapper"-eket pedig stack-en tartod valahol és amikor elhagyod a scope-ot, szépen lefut a destruktor és magától felszabadul a memória.
Ez azért nagyon fontos, mert minden programozó hibázik és nem igazán függ a hibázás gyakorisága attól, hogy mióta űzöd a mesterséget. Ezzel védjük magunkat a memory leak-től.A vector persze elsődlegesen nem pointer wrapper, arra találták ki, hogy nagyon kényelmesen legyen egy bármikor átméretezhető tömböd. A belsejében egy dinamikus tömb van.
-
jattila48
aktív tag
válasz
Teasüti #4153 üzenetére
"Tehát ami nekem átjött ebből a beszélgetésből, hogy ha new operátorral hozok létre tömböt (foglalok le dinamikus memóriát), akkor az egy ún. heap-re kerül,..."
Ez igaz.
"...míg ha new nélkül, akkor a stack-be."
Ez nem feltétlenül igaz, mert a globális adatterületen is deklarálhatsz tömböt.
Egyéb gyakorlati jelentősége pedig az, amit eddig leírtam. Röviden összefoglalva:
- A tömb név nem változó, nem adhatsz neki értéket, és nem képezheted a címét.
-A pointer változó, ami memória címet tartalmaz (pl. a heapen lefoglalt memória címét, de lehet más pl. "hagyományosan" deklarált tömb címe is). A pointer értéke megváltoztatható, és a címe is képezhető.
-Tömböt csak konstans méretűt deklarálhatsz (kivéve C99), míg new-val változó méretű memóriát foglalhatsz.
-Tömböt nem szabad felszabadítani, new-val létrehozott memóriát pedig fel kell szabadítani.
Kb. ennyi ami gyakorlatban különbség a két fogalom között, és amiről minden programozónak tudnia kell.
Még egy "apróság": C++ -ban tömb név, mint konstans pointer lehet template argumentum (mivel fordítási időben kiértékelhető), pointer viszont nem (mivel csak futási időben értékelhető ki). -
jattila48
aktív tag
válasz
Teasüti #4135 üzenetére
"De hisz a tömb is egy pointer.
"
Nem, nem az! C-ben valóban hasonlóan kezelheted a tömböt és a pointert, de ettől még a tömb nem pointer. Sok félreértés és hiba forrása ez, ugyanakkor nagyon kényelmes is tud lenni. A pointer egy változó, ami történetesen memória címet tartalmaz. Mint minden változónak, neki is van címe, és megváltoztathatod az értékét (balérték). Ezzel szemben a tömb egy konstans memória cím (ahol a tönb kezdődik). Ezt a konstanst a fordító/linker/betöltő számolja ki, amit te nem változtathatsz meg, és a címét sem képezheted (hiszen nem is létezik a memóriában).
int tomb[10];
tomb=new int[10]; //Hiba! tombnek nem lehet erteket adni, hiszen az konstans
int **ppi=&tomb; //Hiba! tombnek nem kepezheto a cime, mert az nem valtozo
int *pi=new int[10]; //OK
int **ppi=π //OK valtozonak kepezheto a cime
pi=new int[10]; //OK valtozo erteke megvaltoztathatoAmikor tömb elemre hivatkozol (kiindexeled), a fordító ehhez a konstans címhez adja hozzá az indexet, és erről a címről veszi elő a tömb elemet (intelnél egyetlen utasítás pl. : mov eax, DWORD PTR[ebx+0x1000]; indirekt indexelt címzési mód, ahol 0x1000-nél kezdődik a tömb, ebx-ben pedig az elérni kívánt tömbelem indexe található). Tehát itt a kódba a fordító beleírja a tömb konstans kezdőcímét.
Ha new-val foglalsz helyet, akkor a lefoglalt memória kezdőcímét egy változó kapja értékül, ez a változó a pointer. Ha ezen a memória területen tömb szintaxissal hivatkozol egy elemre, akkor a fordítónak (intel esetén) ehhez legalább két utasításra lesz szüksége. Az elsővel regiszterbe tölti a változó (pointer) címéről a változó értékét (ez maga a new-val foglalt memória kezdőcíme lesz). Ha pl. a pointered címe eax-ben van, akkor mov eax,DWORD PTR[eax] utasítás ezt megoldja. Majd az elem elérése mov eax,DWORD PTR[eax+esi] utasítással történik, ahol az esi tartalmazza azi indexet. Látható, hogy ez jóval lassabb művelet, mint az "igazi" tömb kiindexelése. -
mgoogyi
senior tag
válasz
Teasüti #4135 üzenetére
Igen, így van, a tömböt is pointerként kezeled. Gyakorlatilag a 0. elemére mutató pointer van a változóban értékként.
A kérdésedre a válasz igen, mindig más memóriaterületen kapsz egy új összefüggő memóriaterületet az új tömbödnek. A pointert írasd ki és látod, hogy mindig más értéket kap. Ez a logikai címe a kezdeti memóriacellának (a programod csak a memória egy számára logikailag elkülönített részét látja).
A régi tömb ugyanúgy meglesz az előző ciklusodból, csak a címe már nem lesz meg és anélkül nehéz felszabadítani.
Csináld ciklus belsejében simán, amit írtál. Ha jó sok kört fut a ciklusod, megzabálja a géped memóriáját.
Azért figyelj arra, hogy ne zabálja meg az összeset, kevés elemű int tömböt foglalj le 1000-szer ciklusban, kísérletnek elég. -
mgoogyi
senior tag
válasz
Teasüti #4132 üzenetére
A new meg nem new között az a különbség, hogy a new-val a heap-en foglalsz memóriát, new nélkül meg a stack-en. (itt nem erre a nem szabványos dologra gondolok:
int p [I]= {};
)
Ez utóbbi elég limitált tud lenni, ha majd egyszer írsz rekurzív(önmagát hívó) függvényt, belefuthatsz.
Ezt hívják stackoverflow-nak. Olvass utána, hogy mi az a heap és mi az a stack.
Egyébként paraméterezett méretű tömböt new nélkül nehéz lértehozni.A new (new []) esetében egy pointer-t kapsz vissza és a te feladatod ezt eltakarítani delete-tel ( delete []).
Azért, hogy ezt ne felejtsd el, javasolt olyan osztályokat használni, amik megteszik ezt helyetted.
A vector meghívja helyetted a new[]-t és a delete[]-t, menet közben át is méretezi a benne lévő array-t.
Kényelmessé és biztonságossá teszi a tömbkezelést.
A unique_ptr pedig általánosságban jó arra, hogy egy objektum felszabadításával ne kelljen foglalkozni.Ha ezeket nem használod és elfelejteted a delete-et, akkor keresheted, hogy miért növekszik a progid memóriahasználata (memóriaszivárgás).
-
dabadab
titán
válasz
Teasüti #4132 üzenetére
"Még sose alkalmaztam new-t. Mi szükségem volna rá, ha meg tudom oldani lokális változókkal?"
Ha meg tudod oldani, akkor semmi
Akkor van rá szükséged, ha nem tudod megoldani lokális változókkal (pl mert azt a p[] tömböt visszatérési értékként akarod használni a függvényedben).
Új hozzászólás Aktív témák
Hirdetés
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- ZIDOO médialejátszók
- Gyúrósok ide!
- Samsung Galaxy S23 és S23+ - ami belül van, az számít igazán
- Samsung Galaxy Watch (Tizen és Wear OS) ingyenes számlapok, kupon kódok
- D1Rect: Nagy "hülyétkapokazapróktól" topik
- ThinkPad (NEM IdeaPad)
- Luck Dragon: Asszociációs játék. :)
- Samsung Galaxy S23 Ultra - non plus ultra
- Renault, Dacia topik
- Motorola Edge 50 Neo - az egyensúly gyengesége
- További aktív témák...
- Intel Core Ultra 7 265 /// Bontatlan, Teljesen Új // Üzletből, Számlával és Garanciával
- Csere-Beszámítás! Ryzen 9 9950X Processzor!
- Újszerű Gamer Asztali PC Számítógép 2026-ig Garis ASUS H510M-K R2.0 i5 11400F RTX 4060 8GB Dobozába
- Samsung Galaxy Tab A8 (2021) , 3/32 GB,
- Samsung Galaxy S6 Lite (2022) , 4/64 GB ,Wi-fi
- ÁRGARANCIA!Épített KomPhone Ryzen 7 7700X 32/64GB RAM RTX 5070 GAMER PC termékbeszámítással
- LG 55G3 - 55" OLED evo - 4K 120Hz 0.1ms - MLA - 2000 Nits - NVIDIA G-Sync - AMD FreeSync - HDMI 2.1
- Samsung Galaxy A12 64GB, Kártyafüggetlen, 1 Év Garanciával
- Apple iPhone 14 128GB, Kártyafüggetlen, 1 Év Garanciával
- MikroTik CCR1009-7G-1C-1S+ Cloud Router
Állásajánlatok
Cég: Promenade Publishing House Kft.
Város: Budapest
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest