(1) Terminologie. Numele operatorilor sunt înșelătoare, dar noul este crearea unui obiect. Se compune din alocarea memoriei și apelarea constructorului și ștergerea - distrugerea obiectului, adică sună-l pe distrugător și eliberează memoria. Notă, selectați și eliberați, nu ștergeți.
(2) (Simplu simplificare :) noua operație returnează o valoare a indicelui, iar operația de ștergere ia un indicator ca valoare. Fiți atenți - valoarea în ambele cazuri. Acest lucru înseamnă, în special, că dacă stocați un indicator într-o variabilă, valoarea variabilei nu se va modifica atunci când obiectul este distrus. Ceea ce uneori rănește și rănește să-și amintească.
(3) După eliberare, conținutul memoriei din memorie este imprevizibil. În special, poate fi reutilizat.
int * a = nou int # 40; # 41 ;;
* a = 5;
ștergeți un;
int * b = nou int # 40; # 41 ;;
* b = 3;
printf # 40; "a =, b =.", * a, * b # 41 ;;
int * a = nou int # 40; # 41 ;;
* a = 5;
ștergeți un;
ștergeți un;
Dar există mai multe opțiuni interesante:
int * a = nou int # 40; # 41 ;;
int * b = a;
* a = 5;
ștergeți un;
int * c = nou int # 40; # 41 ;;
* c = 3;
int * d = int nou # 40; # 41 ;;
* d = 7;
printf # 40; "c = .d =.", * c, * d # 41 ;;
Nu se întâmplă aici că c a fost ștearsă neintenționat și se pare că valoarea lui c sa schimbat de la sine.
Pentru cazuri de obezitate severă (plinătatea plinătății):
(1) noul și ștergerea pot fi redefinite nu numai pentru clasele lor, ci și la nivel global. Acest lucru este foarte des folosit în sistemele încorporate, unde standardul alloc () / free () este indisponibil sau nedorit (imaginați-vă o centrală nucleară care nu avea suficientă memorie!).
Dar - frumos - acest lucru poate fi folosit pentru a urmări captura / eliberarea memoriei.
Pe de altă parte, tot acest salt se întâmplă înainte de eliberarea memoriei. Prin urmare, conținutul memoriei se poate modifica cu ajutorul liberei ().
(3) Toți acești indicatori "inteligenți" sunt variabile. nu valori (smartptr
De ce, după blocul de memorie că referințele c indicatorul este marcat ca liber, se schimbă acest bloc?
Implementarea compilatorului, OS, arhitectura PC.
Trebuie să rețineți că compilatorul interacționează foarte atent cu sistemul de operare atunci când memoria dinamică alocă. De fapt, el poate să-i ceară să aloce un alt bloc de memorie pentru heap sau să returneze blocul eliberat în sistem.
În plus, de fiecare dată când programul este pornit, se schimbă la același număr (-572662307).
Deoarece, de fiecare dată când rulați programul "de la zero", cu același mediu, comportamentul sistemului de operare, codul de asamblare al programului dvs., într-un sistem de operare alocat special, o bucată de memorie pentru programul dvs. Chiar și semințele din rand () au o valoare prestabilită definită strict, ceea ce garantează o succesiune constantă de numere aleatoare, dacă le folosiți brusc, iar acest lucru se face intenționat - pentru a simplifica programele de depanare.
Dar, în general, acest lucru nu poate fi cazul.
Înțelegeți un lucru: să înțelegeți ce se întâmplă și cum se întâmplă după ștergerea unui obiect indicat de pointer, înseamnă că ați luat totul, poate până la arhitectura internă și la conducta CPU. Nu vă deranjați cu această întrebare decât dacă sunteți un hacker. Programatorul nu ar trebui să permită astfel de situații în principiu.
invitatul neinvitat a scris:
Aceasta este o declarație foarte puternică. Adevărul nu este întotdeauna și departe de pretutindeni. În primul rând, nu un compilator, ci o bibliotecă. În al doilea rând, biblioteca nu poate interacționa cu axa.
În primul rând, sunt total de acord că malloc este o funcție de bibliotecă.
În al doilea rând, raportul meu are o parte din aproximarea mea, dar aproximarea este rezonabilă. Nu-mi pot imagina cum biblioteca nu poate interacționa cu sistemele de operare moderne atunci când lucrează cu memoria. Mai exact, eu reprezintă două variante:
1. O cantitate limitată de memorie este rezervată în avans sub halda, iar dincolo de acest volum, programul nu poate ieși - malloc va returna NULL atunci când solicită mai multă memorie decât este disponibil în prezent în heap.
2. Se face o încercare de a prelua toată memoria disponibilă pentru acest program. Ei bine, acest lucru este nonsens prin definiție.
Astfel, am ajuns la concluzia că funcțiile de alocare dinamică și de eliberare a memoriei în stadiul actual al dezvoltării tehnologiei informatice sunt pur și simplu obligate să colaboreze îndeaproape cu OS în această chestiune.
invitatul neinvitat a scris:
Nu cunosc bine standardul C ++ și, prin urmare, nu sunt sigur dacă noul () ar trebui să fie difuzat la malloc () sau nu în mod implicit.
invitatul neinvitat a scris:
Simpla cunoaștere a standardului este o cunoaștere foarte specifică. Este, fără îndoială, necesar pentru dezvoltatorul compilatorului și a bibliotecii. Și apoi? Nu știu. Cunoașterea limbajului standard este necesară atunci când se scriu programe portabile - există multe compilatoare diferite.
Încerc să scriu un cod care este inițial portabil, chiar dacă în prezent nu este necesar în proiect. Doar în orice moment poate lua și chiar nevoie.
Desigur, nu am studiat profund standardele, multe au fost deja uitate, dar cu toate acestea, este portabilitatea codului pe care am pus-o într-una din primele cerințe. În caz contrar, abandonăm unul dintre principalele avantaje ale C / C ++ - implementarea acestuia pe aproape toate platformele. Apoi aș prefera ceva mai frumos - Java opimer, pentru special. sarcinilor - python, php, perl, etc. și altele asemenea.
Dar de fapt nu am vrut să spun standarde, ci C ++ în general. Când am citit cartea "C ++" a lui Jeff Elger, mi-am dat seama că, așa cum spunea recent Basha, "știu C ++, dar nu știu cum să scriu programe pe el".
Aceasta poate fi rănită și rănită în mod rezonabil, că spiritul captează. Sunt folosite multe subtilități, pe care programatorii nu le aplică aproape niciodată (în orice caz, experiența mea spune asta).
De aceea pun întrebarea - câte persoane utilizează OOP / C ++ în general, folosind tendințele pe care societatea de dezvoltare C ++ (sau orice se numește) investesc și justifică în fiecare an?
Nu pot să nu spun decât despre Borland'ats - ei în Builder dezactiva mai multe moșteniri din clasele VCL (!). De asemenea, principiul încapsulării este încălcat pretutindeni și așa mai departe.
2. Se face o încercare de a prelua toată memoria disponibilă pentru acest program. Ei bine, acest lucru este nonsens prin definiție
Ei bine, de ce? Aceasta este o strategie absolut normală pentru sistemele încorporate. După sau înaintea inițializării kernelului (în funcție de kernelul folosit), timpul de execuție preia toată memoria și o gestionează.
Pentru un nou este un operator al cărui comportament (non-overloaded) trebuie să rămână previzibil și identic în cadrul cel puțin al acestui compilator, care nu va fi implementat folosind o funcție malloc diferită.
De ce? De ce va deveni imprevizibil?
în timp ce noul este mai bun decât malloc prin faptul că permite verificarea tipului
Acest lucru este imaterial. Este semnificativ faptul că noile apeluri de constructor, și malloc () nu. Comparați cu noua destinație de plasare (fișierul antet
Este evident că noile nu pot interacționa cu malloc () - utilizarea lor într-un singur program este destul de legitimă.
Aceasta poate fi rănită și rănită în mod rezonabil, că spiritul captează. Sunt folosite multe subtilități, pe care programatorii nu le aplică aproape niciodată (în orice caz, experiența mea spune asta).
Un programator (orice) care utilizează limba (orice) pentru a rezolva o problemă, utilizează întotdeauna un anumit subset al limbii. La fel ca limba de a scrie un articol diferă de explicația pentru un stand de bere, acesta diferă de cel pentru Vladimir Vladimirovich ™.
Problemele apar de obicei atunci când fragmente prea mari de limbă rămân în afara acestui subset. În acest caz, există mesaje de eroare indigestibile, "nu este clar ce fac fragmentele programului" etc.