Cuprins:
- Domeniu limitat în C ++
- Examinarea problemei de domeniu în C ++
- Furnizarea unei soluții folosind halda în C ++
Video: ? Ce este un Queue si cum Functioneaza in Procesarea Datelor | Structuri de Date si Algoritmi #4 2024
Mormântul este un bloc amorf de memorie pe care programul C ++ îl poate accesa după cum este necesar. Aflați de ce există și cum se utilizează.
La fel cum este posibil să treci un pointer la o funcție, este posibil ca o funcție să returneze un pointer. O funcție care returnează adresa unui dublu este declarată după cum urmează:
double * fn (void);
Cu toate acestea, trebuie să fii foarte atent atunci când întorci un pointer. Pentru a înțelege pericolele, trebuie să știți ceva despre domeniul de aplicare variabil.
Domeniu limitat în C ++
Domeniul de aplicare este domeniul în care este definită o variabilă. Luați în considerare următorul fragment de cod:
// următoarea variabilă este accesibilă pentru // toate funcțiile și definită atâta timp cât // se execută (domeniul global) int intGlobal; // următoarea variabilă intChild este accesibilă // numai funcției și este definită doar // atâta timp cât C ++ execută funcția child () sau a // funcția pe care apelurile child () (scopul funcției) void child (void) {int intChild;} // urmatoarea variabila intParent are functia // scop void parent (void) {int intParent = 0; copil(); int intLater = 0; (int nArgs, char * pArgs []) {parent ();}
Acest fragment de program începe cu declararea unei variabile intGlobal. Această variabilă există odată cu începerea execuției programului până la terminarea acestuia. Spui că intGlobal are o acoperire de program. "De asemenea, spuneți că variabila" intră în domeniul de aplicare "chiar înainte ca funcția principal () să fie apelată.
Funcția main () invocă imediat părinte (). Primul lucru pe care procesorul îl vede în parinte () este declarația intParent. În acel moment, intParent merge în domeniul de aplicare - adică, intParent este definit și disponibil pentru restul funcției parent ().
A doua instrucțiune în parent () este apelul la copil (). Încă o dată, funcția child () declară o variabilă locală, de data aceasta intChild. Domeniul variabilei intChild este limitat la funcția child (). Din punct de vedere tehnic, intParent nu este definit în domeniul copilului (), deoarece copilul () nu are acces la intParent; cu toate acestea, variabila intParent continuă să existe în timp ce copilul () este executat.
Atunci când copilul () iese, variabila intChild iese din domeniul de aplicare. Nu numai că intChild nu mai este accesibil, ci nu mai există. (Memoria ocupată de intChild este returnată la fondul general pentru a fi folosită pentru alte lucruri.)
Ca mama () continuă să se execute, variabila intLater intră în domeniul de aplicare la declarație. În punctul în care părintele () revine la main (), atât intParent, cât și intLater ies din domeniul de aplicare.
Deoarece intGlobal este declarat global în acest exemplu, este disponibil pentru toate cele trei funcții și rămâne disponibil pentru durata de viață a programului.
Examinarea problemei de domeniu în C ++
Următorul segment de cod se compilează fără eroare, dar nu funcționează (nu urâți că?):
double * child (void) {double dLocalVariable; retur & dLocalVariable;} void părinte (void) {double * pdLocal; pdLocal = copil (); * pdLocal = 1. 0;}
Problema cu această funcție este că dLocalVariable este definită numai în cadrul funcției child (). Astfel, odată ce adresa de memorie a dLocalVariable este returnată de la copil (), se referă la o variabilă care nu mai există. Memoria pe care dLocalVariable a ocupat-o anterior este probabil utilizată pentru altceva.
Această eroare este foarte frecventă, deoarece poate fi târâtă în mai multe moduri. Din păcate, această eroare nu provoacă oprirea instantanee a programului. De fapt, programul poate funcționa bine în majoritatea timpului - adică programul continuă să funcționeze atâta timp cât memoria ocupată anterior de dLocalVariable nu este reutilizată imediat. Asemenea probleme intermitente sunt cele mai dificile pentru rezolvare.
Furnizarea unei soluții folosind halda în C ++
Problema de domeniu a apărut deoarece C ++ a preluat memoria definită local înainte ca programatorul să fie gata. Este nevoie de un bloc de memorie controlat de programator. Poate să aloce memoria și să o pună înapoi atunci când dorește - nu pentru că C ++ crede că este o idee bună. Un astfel de bloc de memorie este numit heap.
Memoria de heap este alocată utilizând noul cuvânt cheie urmat de tipul de obiect pe care îl alocați. Noua comandă rupe o bucată de memorie din gramada suficient de mare pentru a ține tipul de obiect specificat și returnează adresa. De exemplu, următoarele alocă o variabilă dublă din halda:
dublu * copil (void) {double * pdLocalVariable = nou dublu; returnați pdLocalVariable;}
Această funcție funcționează acum corect. Deși variabila pdLocalVariable iese din domeniul de aplicare atunci când funcția child () revine, memoria la care se referă pdLocalVariable nu face. O locație de memorie returnată de noi nu iese din domeniul de aplicare până când nu este returnată în mod explicit la heap folosind ștergerea cuvintelor cheie, care este proiectată special pentru acest scop:
void parent (void) {// child () returnează adresa a unui bloc // de memorie heap dublă * pdMyDouble = copil (); // stocați o valoare acolo * pdMyDouble = 1. 1; // … // returnează acum memoria la ștergerea heapului pdMyDouble; pdMyDouble = 0; // …}
Aici pointerul returnat de copil () este folosit pentru a stoca o valoare dubla. După ce funcția este terminată cu locația de memorie, aceasta este returnată la heap. Funcția parent () stabilește pointerul la 0 după ce memoria heap a fost returnată - aceasta nu este o cerință, dar este o idee foarte bună.
Dacă programatorul încearcă în mod greșit să stocheze ceva în * pdMyDouble după ștergere, programul se va prăbuși imediat cu un mesaj de eroare semnificativ.
Puteți folosi noi pentru a aloca și ele matrice din heap, dar trebuie să returnați un matrice utilizând cuvântul cheie de ștergere:
int * nArray = new int [10]; nArray [0] = 0; ștergeți [] nArray;
Tehnic nou int [10] invocă noul operator [], dar funcționează la fel ca și noul.