Objektumok memóriakezelése belülről
Dobra Gábor · 2019.02.27.
A mai óra célja annak megismerése, hogyan működik az objektumok memóriakezelése belülről.
Felkészülés a gyakorlatra
- Jegyzet 3. fejezete
- Ajánlott a tárolókról szóló exta írás elolvasása.
A main
melyik sorában a Matrix
osztály milyen speciális "tagfüggvényei" hívódnak, milyen sorrendben?
class Matrix
{
// ...
};
Matrix f1()
{
Matrix m(3, 3);
return m;
}
void f2(Matrix s)
{
std::cout << s << std::endl;
}
int main()
{
Matrix m1(1, 3);
Matrix m2(4, 4);
Matrix m3 = m2;
m1 = m3;
m1 = m2 + m3;
m2 += m3;
Matrix m4 = f1();
std::cout << m1 + f1() << std::endl;
f2(m2);
}
Kezel dinamikus memóriát az osztály? Ebből mennyit lát, aki az osztályt használja? Melyik OOP alapelv hogyan járul hozzá ehhez?
Hogyan érjük el a Mátrix egyes elemeit?
Ha az igazi indexelő operátort akarnánk használni, sok problémába futhatunk bele:
Matrix m(2, 4);
std::cout << m[1, 3]; // BAJ VAN, kétparaméteres indexelő operátor nincs...
std::cout << m[3]; // ...és a vessző operátor miatt ez történne a fenti sorban is
std::cout << m[1][3]; // így oké lenne, de...
std::cout << m[1]; // ...ez milyen típus? egész sor? vagy oszlop?
std::cout << m[][3]; // ...és ha van sor, akkor miért nincs oszlop?
Trükk: a mátrixok nekünk amúgy is csak egyes elemek szintjén érdekes, teljes sorokat / oszlopokat ne akarjunk kérni. Az elemek elérésére használjunk kétparaméteres függvényhívás operátort! Melyik zárójelpár mit jelent?
Matrix m(2, 4);
std::cout << m(1, 3) << std::endl;
std::cout << Matrix(2, 4)(1, 3) << std::endl;
return Matrix(2, 4);
Megoldás
- konstruktor
- indexelő operátor
- konstruktor, aztán indexelő operátor
- konstruktor
Mivel az elemeket csak egyesével érheti el kívülről, aki az osztályt használja, ezért nem muszáj oszloponként / soronként tárolni, lehet sorfolytonosan is, InfoC-n a 0. módszer is használható.
Ezzel sokkal egyszerűbbé válik a memóriakezelés. Milyen adattagokra van szükség? Hogyan fog működni az indexelés? Írjátok meg a függvényhívás operátorokat! Miért kell belőle kettő?
Ha csak egyesével lehet hozzáférni az elemekhez, akkor a belső implementációnak jóval több szabadságot adunk: lehetne pl. ritka mátrixként tárolni, csak a nemnulla elemeket téve egy láncolt listába, memóriahatékonyan.
A +
és a +=
operátor lehet globális, vagy érdemes tagfüggvényként implementálni? Írjuk meg a Matrix
összeadó operátorait!
Tipp
Ha a magasságot és a szélességet le lehet kérdezni a mátrixtól, akkor az operátorok könnyen lehetnek globálisak.
Ha viszont tagfüggvényként implementáljuk, nem kell két ciklus a bejáráshoz, elég egy, hiszen ismerjük az adatszerkezetet, lehet sorfolytonos a bejárás.
Mi írjuk meg globálisként!