Dynamická správa paměti (operátory new a delete)

C++ Pokročilé konstrukce v C++ Dynamická správa paměti (operátory new a delete)

Existují dva základní způsoby alokace paměti. Statická a dynamická. Při statické alokaci je již při kompilaci známo kde se alokuje jaké množství paměti a jakého datového typu bude, stejně tak kdy se paměť dealokuje. Je to prostě deklarace proměnné, objektu nebo pole proměnných či objektů. Někdy ale potřebujeme, aby se paměť alokovala pouze za určitých podmínek, její množství (a třeba i datový typ) bylo určeno až za běhu programu, mohli jsme k ní přistupovat odkudkoliv a podle daných podmínek určili, kdy se paměť dealokuje. Tomu se říká dynamická správa paměti a realizuje se pomocí operátorů new a delete.

Operátor new

Operátor new dělá tři věci. Zaprvé alokuje paměť podle daného datového typu. Zadruhé pokud vytváří objekt třídy, zavolá její konstruktor. Zatřetí vrátí adresu nově alokované paměti. Syntaxe je následující:

int* ptr;  //deklarace pointeru ptr
ptr = new int;  //vytvoření a přiřazení paměti, za klíčovým slovem new následuje název datového typu

Při alokaci je možné paměť rovnou inicializovat, pomocí hodnoty uvedené v závorkách za datovým typem.

int* ptr = new int(100);  //vytvoří data typu int a inicializuje je na hodnotu 100, adresu vrátí pointeru ptr, přes který můžeme k datům přistupovat

Při dynamickém vytvoření objektu nějaké třídy, se do závorek udávají parametry konstruktoru.

class trida
{
  private:
    ...
  public:
    trida(){...}
    trida(int param, int param2){...}
    ...
};

...

trida* objekt = new trida;  //vytvoří objekt třídy, zavolá bezparametrický konstruktor a adresu objektu vrátí pointeru objekt
trida* objekt2 = new trida(50,70);  //vytvoří objekt třídy, zavolá konstruktor přebírající dvě hodnoty typu int a předá mu čísla 50 a 70

Operátor delete

Operátor delete dělá dvě věci. Zaprvé, v případě ze odstraňuje objekt nějaké třídy, volá její destruktor, zadruhé dealokuje paměť. Syntaxe je následující:

int* ptr = new int;
delete ptr;  //dealokuje paměť na kterou ukazuje pointer ptr
trida* objekt = new trida(50,70);
delete objekt;  //zavolá destruktor objektu na který ukazuje pointer objekt a dealokuje jeho paměť

Operátor delete zachází s pamětí, kterou dealokuje, podle datového typu, kterého je pointer, který operátoru předáváme. Lépe řečeno...

int* ptr = (int*)new char;
delete ptr;

...tohle nedělejte.

Takovouhle krkolomnost ovšem udělat můžete.

int* ptr = (int*)new char;
delete (char*)ptr;  //ptr je sice typu int*, ale díky explicitní konverzi ho operátor delete bere jako char*

Možná si říkáte k čemu je tohle všechno vlastně dobré. Využití může být spousta, uvedu příklad související s dědičností. Uvažujme následující situaci.

class Auto {...};
class NakladniAuto : public Auto {...};
class OsobniAuto : public Auto {...};

Řekněme že chceme vytvořit pole aut. Do prvků tohoto pole ovšem mohou být přiřazeny jak auta nákladní tak osobní.

Auto cars[velikost];  //deklarace pole objektů třídy Auto
cars[0] = OsobniAuto(parametry);  //vytvoření nového objektu třídy OsobniAuto pomocí konstruktoru a zkopírování tohoto objektu do objektu cars[0]
NakladniAuto nAuto;  //vytvoření objektu třídy NakladniAuto
cars[20] = nAuto;  //zkopírování objektu nAuto do objektu cars[20]

Toto je syntakticky v pořádku, fungovat to ale nebude. Při kopírování objektů odvozených tříd do objektu třídy základní se objekt ořeže a zbude z něj objekt základní třídy, v tomto případě Auto. Můžeme ale použít pole pointerů a objekty vytvářet pomocí operátoru new.

Auto* cars[velikost];  //deklarace pole pointerů třídy Auto
cars[0] = new OsobniAuto(parametry);  //vytvoření nového objektu třídy OsobniAuto pomocí operátoru new, adresa objektu je přiřazena pointeru cars[0]
NakladniAuto nAuto;  //vytvoření objektu třídy NakladniAuto
cars[20] = new NakladniAuto;  //vytvoření nového objektu třídy NakladniAuto pomocí operátoru new, adresa objektu je přiřazena pointeru cars[20]
*((NakladniAuto*)cars[20]) = nAuto;  //zkopírování objektu nAuto do objektu na jehož adresu ukazuje pointer cars[20], pointer musí být přetypován na pointer odvozené třídy
...
for(int i=0;i<velikost;i++)
  delete cars[i];            //nesmíme zapomenout nakonec objekty dealokovat

Pointer může ukazovat na objekt základní třídy, stejně tak na objekt jakékoliv třídy od ní odvozené. Tohle tedy fungovat bude.

V druhé části vysvětlím, jak spravovat dynamická pole pomocí operátorů new[] a delete[].


 

  Aktivity (3)

Článek pro vás napsal Lukáš Hruda (Luckin)
Avatar
...

Jak se ti líbí článek?
Celkem (4 hlasů) :
55555


 


Miniatura
Předchozí článek
Ukazatele v C++
Miniatura
Všechny články v sekci
Pokročilé konstrukce v C++

 

 

Komentáře

Avatar
Lukáš Hruda (Luckin):

Byl bych rád za nějaký feedback, abych věděl, jestli má cenu dělat časem další tutoriály. Předem díky...

 
Odpovědět 17.3.2013 19:06
Avatar
Odpovídá na Luboš Běhounek (Satik)
Lukáš Hruda (Luckin):

Ok... Příště udělám pravděpodobně reference :D

 
Odpovědět 17.3.2013 20:01
Avatar
Maxfx
Redaktor
Avatar
Maxfx:

a co třeba knihovnu stl :D byl bych rád :) ale dobrý :D

Odpovědět 17.3.2013 23:43
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Odpovídá na Maxfx
Lukáš Hruda (Luckin):

STL jsem nikdy moc nepoužíval...

Editováno 17.3.2013 23:53
 
Odpovědět 17.3.2013 23:51
Avatar
Odpovídá na Maxfx
Lukáš Hruda (Luckin):

Navíc bych chtěl spíš udělat tutoriály na různé pokročilejší techniky jazyka jako takového, k tomu je ale potřeba nejdřív vysvětlit základy, jelikož tu k C++ moc materiálů není.

 
Odpovědět 18.3.2013 0:05
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Maxfx:

Ja to chápu ale toho je na internetu tuna

Odpovědět 18.3.2013 14:01
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Odpovídá na Maxfx
Lukáš Hruda (Luckin):

Tak to na STL taky... a zkus třeba najít nějakej slušnej tutoriál na šablony, virtuální dědičnost, přetěžování operátorů a podobně... oni existujou, ale co jsem koukal tak nejsou moc podrobný. Navíc STL je na spoustě z těchhle věcí postavený, především ty šablony, přetěžování operátorů, konverzní/kopí­rovací konstruktory, konverzní funkce... Když neumíš tohle a začneš se učit STL, tak vůbec nebudeš vědět jak to funguje a to imho neni správnej přístup k programování.

 
Odpovědět 18.3.2013 14:25
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Maxfx:

ok když to bude podrobný budu rád :)

Odpovědět 18.3.2013 19:59
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.