Risi dhe fshij (C++)

p = new T(argument);Në gjuhën e programimit C++ ,  dhe  janë një çift i konstrukteve gjuhësore që kryejnë shpërndarje dinamike të memories, ndërtimin e objektit dhe shkatërrimin e objektit . 

 Vështrim i përgjithshëm 
Përveç një forme të quajtur "vendosje e re", the operatori  tregon një kërkesë për shpërndarje memorie në grumbullin e një procesi. Nëse disponohet memorie e mjaftueshme,  inicializon memorien, duke thirrur konstruktorët e objekteve nëse është e nevojshme, dhe e kthen adresën në memorien e re të alokuar dhe të inicializuar.   A kërkesa , në formën e saj më të thjeshtë, duket si më poshtë:p = new T [N];ku  është një tregues i tipit i deklaruar më parë  (ose ndonjë lloj tjetër për të cilin a Treguesi  mund të caktohet, si p.sh. një superklasë e  ). Konstruktori i paracaktuar për , nëse ka, thirret për të ndërtuar a Shembull  në buferin e ndarë të memories.

Nëse jo  është instaluar,  në vend të kësaj hedh një përjashtim të llojit  . Kështu, programi nuk ka nevojë të kontrollojë vlerën e treguesit të kthyer, siç është zakon në C ; nëse nuk bëhej përjashtim, shpërndarja kishte sukses.

Homologu i shpërndarjes së  eshte , i cili fillimisht thërret destruktorin (nëse ka) në argumentin e tij dhe më pas kthen memorien e alokuar nga  në dyqanin falas. Çdo thirrje për  duhet të përputhet me një telefonatë në  ; dështimi për ta bërë këtë shkakton një rrjedhje të kujtesës . 

  syntax has several variants that allow finer control over memory allocation and object construction. A function call-like syntax is used to call a different constructor than the default one and pass it arguments, e.g.,p = new T[N] {initializer1, ..., initializerN};quan një argument të vetëm Konstruktori  në vend të konstruktorit të paracaktuar kur inicializon buferin e sapondarë.

Një variant i ndryshëm shpërndan dhe inicializon vargjet e objekteve në vend të objekteve të vetme:#include <cstdlib>
#include <cstddef>

class Singleton {
public:
 static void* operator new(std::size_t size) {
  if (!instance) {
   instance = std::malloc(size);
  }
  refcount++;
  return instance;
 }

 static void operator delete(void*) noexcept {
  if (--refcount == 0) {
   std::free(instance);
   instance = nullptr;
  }
 }

private:
 static void* instance = nullptr;
 static std::size_t refcount = 0;
};Kjo kërkon një tampon memorie nga dyqani falas që është mjaft i madh për të mbajtur një grup të afërt  objekte të tipit , dhe thërret konstruktorin e paracaktuar në çdo element të grupit.

Memoria e alokuar me  duhet të shpërndahet me , në vend të  . Përdorimi i formës së papërshtatshme rezulton në sjellje të papërcaktuar . Përpiluesit C++ nuk kërkohet të gjenerojnë një mesazh diagnostikues për përdorimin e formularit të gabuar.

Standardi C++11 specifikon një sintaksë shtesë,p = new T;që inicializon secilën   .

 Trajtimi i gabimeve 
Nëse  nuk mund të gjejë memorie të mjaftueshme për të shërbyer një kërkesë alokimi, ajo mund të raportojë gabimin e saj në tre mënyra të ndryshme. Së pari, standardi ISO C++ lejon programet të regjistrojnë një funksion të personalizuar të quajtur a  me kohën e ekzekutimit në C++; nëse po, atëherë ky funksion thirret kurdoherë  ndeshet me një gabim. Të  mund të përpiqet të ofrojë më shumë memorie ose të përfundojë programin nëse nuk mundet.

Nëse nuk ka memorie të mjaftueshme në dyqanin falas për një objekt të llojit , të kërkesa  tregon dështimin duke hedhur një përjashtim të llojit  . Kjo heq nevojën për të kontrolluar në mënyrë eksplicite rezultatin e një alokimi.

Metoda e tretë e trajtimit të gabimeve sigurohet nga forma e variantit , i cili specifikon se nuk duhet hedhur asnjë përjashtim; në vend të kësaj, një tregues null kthehet për të sinjalizuar një gabim shpërndarjeje.

 Mbingarkim 
Të operatori  mund të mbingarkohet në mënyrë që lloje të veçanta (klasa) të përdorin algoritme të shpërndarjes së memories të personalizuara për instancat e tyre. Për shembull, në vijim është një variant i modelit singleton ku i pari Thirrja  alokon një shembull dhe të gjitha thirrjet pasuese kthejnë të njëjtin shembull:

Kjo veçori ishte e disponueshme që herët në historinë e C++, megjithëse mekanizmi specifik i mbingarkesës ndryshoi. Ajo u shtua në gjuhë sepse programet C++ të orientuara drejt objekteve prireshin të ndanin shumë objekte të vogla me , e cila përdori përbrenda alokatorin C (shih  ); që, megjithatë, ishte optimizuar për alokimet më të pakta dhe më të mëdha të kryera nga programet tipike C. Stroustrup raportoi se në aplikimet e hershme, funksioni C  ishte "blloku më i zakonshëm i performancës në sistemet reale", me programet që shpenzonin deri në 50% të kohës së tyre në këtë funksion. [4]

 Lidhja me malloc dhe pa pagesë 
Meqenëse standardi C++ përfshin bibliotekën standarde C, rutinat e ndarjes së memories dinamike C  ,  ,  dhe  janë gjithashtu të disponueshme për programuesit C++. Përdorimi i këtyre rutinave është i dekurajuar për shumicën e përdorimeve, pasi ato nuk kryejnë inicializimin dhe shkatërrimin e objektit.  të reja dhe , në fakt, u prezantuan në versionin e parë të C++ (atëherë i quajtur " C me klasa ") për të shmangur domosdoshmërinë e inicializimit manual të objektit. 

Në ndryshim nga rutinat C, të cilat lejojnë rritjen ose tkurrjen e një grupi të caktuar me , nuk është e mundur të ndryshohet madhësia e një buferi memorie të alokuar nga  . Në vend të kësaj, biblioteka standarde C++ ofron një grup (koleksion) dinamik që mund të zgjerohet ose zvogëlohet në të Klasa e shabllonit  .

Standardi C++ nuk specifikon asnjë lidhje ndërmjet  /  dhe rutinat e ndarjes së memories C, por  dhe  zakonisht zbatohet si mbështjellës përreth  dhe  .  Përzierja e dy familjeve të operacioneve, p.sh.  kujtesa  e alokuar ose  'ing memoria , shkakton sjellje të padefinuar dhe në praktikë mund të çojë në rezultate të ndryshme katastrofike si mos lirimi i bravave dhe rrjedhimisht bllokimi .  Section 4.4, Common C++ Memory Management Errors.

 Shihni gjithashtu 

 Përcaktues (C++)
 Trajtimi me përjashtim
 Pishina e memories
 Pointer (programim kompjuterik)
 Përvetësimi i burimeve është inicializimi (RAII)
 Tregues të zgjuar

 Referime 

Kategoria:Gjuhë programimi