Ugrás a tartalomhoz

C++ dynamic memory allocation

A Wikiszótárból, a nyitott szótárból


Főnév

C++ dynamic memory allocation (tsz. C++ dynamic memory allocations)

  1. (informatika) dinamikus memóriafoglalás

A memória az egyik legfontosabb erőforrás egy számítógépes program számára. A programoknak hatékonyan kell kezelniük a memóriát, hogy elkerüljék a túlzott memóriahasználatot, a szivárgásokat és a teljesítményproblémákat. A C++ kétféle memóriafoglalást kínál:
1. Statikus memóriafoglalás – A változók a program fordításakor kapnak helyet a memóriában, és a lefoglalt méret fix marad.
2. Dinamikus memóriafoglalás – A program futása közben történik a memóriafoglalás és -felszabadítás, ami lehetővé teszi a rugalmasabb memóriahasználatot.

1. Dinamikus memóriafoglalás C++ nyelven

A dinamikus memóriafoglalás lehetővé teszi, hogy a program a futásidőben hozzon létre új változókat, és csak akkor foglalja le a szükséges memóriát, amikor ténylegesen szükség van rá. Ehhez a new és delete kulcsszavakat használjuk.

1.1. Az new operátor használata

Az new operátor segítségével dinamikusan tudunk memóriát foglalni. Az alábbi példában egy egész számra foglalunk helyet a heap memóriában:

#include <iostream>

int main() {
    int* ptr = new int;  // Egy egész számra foglalunk helyet
    *ptr = 10;           // Értéket adunk neki
    
    std::cout << "A dinamikusan foglalt változó értéke: " << *ptr << std::endl;

    delete ptr;  // Memória felszabadítása
    return 0;
}

Ebben a példában:
- A new int lefoglal egy helyet az egész számnak.
- A ptr pointer erre a memóriacímre mutat.
- Az értéket közvetlenül a pointer segítségével módosítjuk.
- A delete ptr felszabadítja a lefoglalt memóriát.

Ha nem szabadítjuk fel a memóriát, akkor memóriaszivárgás történik, ami hosszú távon komoly problémát jelenthet.



1.2. Az new[] operátor és dinamikus tömbök

Ha nem egyetlen változóra, hanem egy tömbre van szükségünk, akkor a new[] operátort kell használni:

#include <iostream>

int main() {
    int* arr = new int[5]; // 5 elemű tömb lefoglalása

    // Tömb inicializálása
    for (int i = 0; i < 5; i++) {
        arr[i] = i * 10;
    }

    // Tömb kiíratása
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    delete[] arr; // Memória felszabadítása
    return 0;
}

Fontos megjegyzések:
- A tömb lefoglalásához a new[] operátort használjuk.
- A tömb elemei pointeren keresztül elérhetők.
- A memória felszabadításához a delete[] operátort kell használni, nem pedig a delete-et!



2. A delete és delete[] operátorok

A dinamikusan foglalt memória kézi felszabadítása elengedhetetlen, különben memóriaszivárgás történhet.

Foglalás módja Felszabadítás módja
new delete
new[] delete[]

Ha elfelejtjük a delete vagy delete[] használatát, az lefoglalt memóriaterület a program futása alatt továbbra is foglalt marad, ami memóriahasználati problémákhoz vezethet.



3. Okos mutatók (std::unique_ptr, std::shared_ptr)

A modern C++ lehetőséget ad a memória automatikus kezelésére okos mutatókkal. Ezek segítségével elkerülhetők a memóriafelszabadítási hibák.

3.1. std::unique_ptr – Egyedi tulajdonú mutató

A std::unique_ptr egy olyan okos mutató, amely biztosítja, hogy az adott memóriafoglalás csak egy mutatóhoz tartozzon.

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(100);
    std::cout << "Az érték: " << *ptr << std::endl;

    // A memória automatikusan felszabadul, amikor a ptr kilép a hatókörből
    return 0;
}

Itt nincs szükség delete-re, mert amikor a ptr változó hatóköre véget ér, a memória automatikusan felszabadul.



3.2. std::shared_ptr – Megosztott mutató

A std::shared_ptr lehetővé teszi, hogy egy memóriaterületet többen is használjanak, és az automatikusan felszabadul, ha senki sem használja.

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
    std::shared_ptr<int> ptr2 = ptr1; // Több mutató is hivatkozhat ugyanarra az erőforrásra

    std::cout << "Érték: " << *ptr1 << std::endl;
    std::cout << "Használatok száma: " << ptr1.use_count() << std::endl;

    return 0;
}

A shared_ptr egy referenciaszámlálót használ annak nyomon követésére, hogy hány mutató hivatkozik az adott erőforrásra. Amikor az utolsó shared_ptr is megszűnik, a memória felszabadul.



4. Memóriaszivárgások és tipikus hibák

A memóriaszivárgás az egyik leggyakoribb probléma a dinamikus memóriakezelésben. Néhány gyakori hiba:

  1. Elfelejtett delete hívás

    int* ptr = new int(10);
    // Ha nincs delete ptr, memóriaszivárgás történik
    
  2. Többszörös felszabadítás (double delete)

    int* ptr = new int(10);
    delete ptr;
    delete ptr; // Hiba! A memóriát már felszabadítottuk!
    
  3. Visszatérés egy felszabadított mutatóra (dangling pointer)

    int* ptr = new int(10);
    delete ptr;
    std::cout << *ptr; // Hiba! A mutató már nem mutat érvényes memóriára!
    



Összegzés

  • A new és delete segítségével dinamikusan foglalhatunk és szabadíthatunk fel memóriát.
  • A new[] és delete[] tömbökre vonatkozik.
  • Az okos mutatók (std::unique_ptr, std::shared_ptr) segítenek a memória automatikus kezelésében.
  • Mindig figyeljünk a memóriaszivárgások és hibák elkerülésére!

A dinamikus memóriafoglalás hatékony eszköz, de felelősségteljes használatot igényel.