C++-kieli‎ > ‎

Muistin varaus

Muistin varaukset keosta (heap)

Muistin virkistämiseksi: C-kielen muistinvaraukset.

HUOM! Kaikki muistit, jotka varataan tulee vapauttaa !!!

Dynaaminen muistinvaraus

Kaikkia tietotyyppejä voidaan luoda staattisesti ja dynaamisesti.

Varataan muisti muuttujalle staattisesta muistista:

int Paino;

Tämä varaa muistin pinosta (stack).

Sama voidaan toteuttaa kekoon (heap) dynaamisella muistinvarauksella:

int* Paino = new int;

Tämä tulee muistaa vapauttaa delete-käskyllä:

delete Paino;

Muuten ohjelmaan tulee muistivuoto.

Useamman yksikön kokoisten muistien varaaminen

Muistia voidaan varata enemmän kuin yksi muuttuja kerrallaan, rajana on vapaan muistin määrä (tosin virtuaalimuistit muuttavat tämän rajan). Varaaminen tapahtuu kuten yhden yksikön varaaminen, mutta koko määritellään []-operaattorilla:

int* Taulu = new int[10];

Muistin vapauttaminen tapahtuu delete [] -käskyllä, hakasulut pitää olla, kun vapautetaan useampi varausyksikkö.

delete [] Taulu;

Dynaaminen muistinvaraus luokan sisällä

Esimerkki 1. Luokan jäsenmuuttujien luominen kekoon.

class CElain
{
private:
    char* m_Nimi;               // O soitin, char-tyyppiä
    float* m_Massa;             // Osoitin, float-tyyppiä

public:
    CElain() {
        m_Nimi =  new char[100]; // Varataan muistia sadalle char:lle.
        m_Massa =  new float;    // Varataan muistia yhdelle float:lle.

        strcpy(m_Nimi, "");     // Alustetaan m_Nimi tyhjäksi merkkijonoksi.
         *m_Massa = 0.0;         // Alustetaan m_Massa nollaksi, HUOM. *m_Massa, sillä m_Massa on osoitin !
    }

    ~CElain() {
         delete [] m_Nimi;       // Vapautetaan sadan char:in muisti, HUOM: [], kun kyseessä taulukko !
         delete m_Massa;         // Vapautetaan float:in muisti.
    }
};

Kuten tästä esimerkistä huomataan, tulee jäsenmuuttujien muisti varata muodostimessa ja vapauttaa hajoittimessa.

Osoittimien käyttö (kertauksena)

Kun käsitellään osoittimia, tulee muistaa että osoitin pitää sisällään nimenomaan muistiosoitteen. Kun halutaan muuttaa osoittimen osoittamaa arvoa (muistin sisältää), niin tulee tähti (*) osoittimen eteen:

*Nimi = 6;  // Asettaa Nimi-osoittimen osoittamaan muistipaikan sisällön arvoon 6.

Jos tähteä ei käytettäisi, muutettaisiin muistiosoitetta, ei muistin sisältää.

Nimi = 6;  // Asettaa Nimi-osoittimen osoittamaan muistipaikkaan 6.

Jos kääntäjä antaisi tämän mennä läpi (sen tulisi antaa virheilmoitus), tämä sijoittaisi Nimi-osoittimen osoittamaan muistipaikkaan 6. Jos tämän jälkeen yritettäisiin kirjoittaa Nimi-osoittimen osoittamaan muistipaikkaan, se kaataisi ohjelman, sillä muistipaikka 6 ei ole (normaalisti) ohjelmoijan käytettävissä.

Luokkien luominen dynaamiseen muistiin

Aivan kuten tavallisten tietotyyppien kanssa, luokat voidaan luoda pinoon ja kekoon. Huomaamisen arvoista on se, että kun kekoon luotua oliota käsitellään, muuttuu piste (.) nuoleksi (->).

Esimerkki 2. CElain-luokka, josta tehdään kaksi oliota, toinen pinoon ja toinen kekoon.

class CElain
{
private:
    char m_Nimi[100];
    float m_Massa;

public:
    bool AsetaNimi(char Nimi[]);
    bool KysyNimi(char Nimi[]);
    bool AsetaMassa(float Massa);
    bool KysyMassa();
};

int main()
{
    CElain kissa;               // Olio kissa luodaan pinoon.
    kissa.AsetaNimi("Miuku");

    CElain* koira = new CElain;  // Olio koira luodaan kekoon.
    koira ->AsetaNimi("Rekku");  // Huom! ->
    delete koira;               // Vapautetaan varattu muisti.
}

Esimerkki 3. Varataan tilaa taulukolle.

#include <iostream>

namespace std;

int main()
{
    const int alkiot = 10;
    cout << "Varataan " << alkiot << " alkiota... ";
     double *taulu = new taulu[alkiot]; // Varataan alkio-luvun verran double-muuttujia.

    if (taulu != NULL) {
        cout << "\nVaraus onnistui alueelle: " << &taulu << " - " << &taulu[alkiot];
        cout << " eli " << &taulu[alkiot] - &taulu[0] << " alkiota.\n\n";
        alkiot *= 10;
    } else {
        cout << "VARAUS EI ONNISTUNUT!" << endl;
    }

    cout << "\n\n";
    delete  [] taulu; // Vapautetaan varattu muisti, Huom! []

    return 0;
}

HUOM! Kaikki muistit, jotka varataan tulee vapauttaa !!!

Comments