LA CAMPANA

C'è chi legge questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vuoi leggere The Bell
Niente spam

Allocazione dinamica e statica della memoria. Vantaggi e svantaggi. Allocazione di memoria per singole variabili usando i nuovi operatori ed elimina. Possibili situazioni critiche durante l'allocazione della memoria. Inizializzazione sull'allocazione della memoria

1. Allocazione dinamica e statica (fissa) della memoria. Principali differenze

Per lavorare con array di informazioni, i programmi devono allocare memoria per questi array. Per allocare memoria per array di variabili, vengono utilizzati gli operatori, le funzioni, ecc. Corrispondenti Nel linguaggio di programmazione C ++, si distinguono i seguenti metodi di allocazione della memoria:

1. Statico (fisso) allocazione della memoria. In questo caso, la memoria viene allocata una sola volta al momento della compilazione. La dimensione della memoria allocata è fissa e invariata fino alla fine dell'esecuzione del programma. Un esempio di tale allocazione è la dichiarazione di un array di 10 numeri interi:

int M; // la memoria per l'array viene allocata una volta, la dimensione della memoria è fissa

2. Dinamico allocazione della memoria. In questo caso, viene utilizzata una combinazione di operatori new ed delete. Il nuovo operatore alloca la memoria per una variabile (array) in un'area di memoria speciale chiamata "heap". L'operatore di eliminazione rilascia la memoria allocata. Ogni nuovo operatore deve avere il proprio operatore di eliminazione.

2. Vantaggi e svantaggi dell'utilizzo di metodi di allocazione della memoria dinamici e statici

L'allocazione dinamica della memoria presenta i seguenti vantaggi rispetto all'allocazione della memoria statica:

  • la memoria è allocata secondo necessità a livello di programmazione;
  • nessuno spreco inutile di memoria inutilizzata. Quanta memoria viene allocata quanto basta e se necessario;
  • è possibile allocare memoria per matrici di informazioni, la cui dimensione è a priori sconosciuta. La determinazione della dimensione dell'array viene formata durante l'esecuzione del programma;
  • è conveniente riallocare la memoria. O in altre parole, è conveniente allocare un nuovo frammento per lo stesso array se è necessario allocare memoria aggiuntiva o memoria libera non necessaria;
  • con un modo statico di allocare memoria, è difficile riallocare la memoria per una variabile di matrice, poiché è già allocata fissa. Nel caso di un metodo di selezione dinamica, ciò avviene in modo semplice e conveniente.

Vantaggi di un modo statico di allocare memoria:

  • è meglio utilizzare l'allocazione di memoria statica (fissa) quando la dimensione dell'array di informazioni è nota e rimane invariata durante l'esecuzione dell'intero programma;
  • l'allocazione di memoria statica non richiede ulteriori operazioni di rilascio mediante l'operatore di eliminazione. Ciò comporta meno errori di programmazione. Ogni nuovo operatore deve avere il proprio operatore di eliminazione;
  • naturalezza (naturalezza) della presentazione del codice del programma che opera con array statici.

A seconda dell'attività da svolgere, il programmatore deve essere in grado di determinare correttamente quale metodo di allocazione della memoria è adatto per l'una o l'altra variabile (array).

3. Come allocare memoria usando il nuovo operatore per una singola variabile? Forma generale.

La forma generale di allocazione della memoria per una singola variabile utilizzando il nuovo operatore è la seguente:

ptrName \u003d nuovo tipo;
  • ptrName - il nome della variabile (puntatore) che punterà alla memoria allocata;
  • genere - il tipo di variabile. La dimensione della memoria è allocata sufficiente per memorizzare il valore di una variabile di questo tipo genere .
4. Come liberare la memoria allocata per una singola variabile usando l'operatore delete? Forma generale

Se la memoria per una variabile viene allocata con il nuovo operatore, dopo la fine dell'uso della variabile, questa memoria deve essere rilasciata con l'operatore di eliminazione. In C ++, questo è un prerequisito. Se la memoria non viene liberata, la memoria rimarrà allocata (occupata), ma nessun programma può utilizzarla. In questo caso, ci sarà "perdita di memoria" (perdita di memoria).

In Java, nei linguaggi di programmazione C #, non è necessario liberare memoria dopo l'allocazione. Questo viene fatto dal Garbage Collector.

La forma generale dell'operatore di eliminazione per una singola variabile è:

elimina ptrName;

dove ptrName - il nome del puntatore per il quale la memoria era stata precedentemente allocata dal nuovo operatore. Dopo aver eseguito l'operatore di eliminazione, il puntatore ptrName indica un pezzo di memoria arbitrario che non è riservato (allocato).

5. Esempi di allocazione (nuova) e liberazione (eliminazione) della memoria per puntatori di tipi base

Gli esempi dimostrano l'uso dei nuovi operatori ed eliminano. Gli esempi sono semplificati.

Esempio 1. Puntatore al tipo int. Esempio più semplice

// allocazione della memoria utilizzando il nuovo operatore int * p; // puntatore a int p \u003d new int; // alloca memoria per il puntatore * p \u003d 25; // scrive valori in memoria // usa la memoria allocata per il puntatore int d; d \u003d * p; // d \u003d 25 // memoria libera allocata per il puntatore - richiesta elimina p;

Esempio 2 Puntatore per digitare double

// allocazione di memoria per raddoppiare un puntatore double * pd \u003d NULL; pd \u003d nuovo doppio; // alloca memoria if (pd! \u003d NULL) (* pd \u003d 10.89; // scrivi valori doppio d \u003d * pd; // d \u003d 10.89 - utilizzare nel programma // memoria libera elimina pd; )
6. Che cos'è una perdita di memoria?

« Perdita di memoria"- questo è quando la memoria per una variabile viene allocata dal nuovo operatore e alla fine del programma non viene rilasciata dall'operatore di eliminazione. In questo caso, la memoria del sistema rimane occupata, sebbene non sia più necessario utilizzarla, poiché il programma che l'ha utilizzata ha da tempo completato il suo lavoro.

La perdita di memoria è un tipico errore del programmatore. Se la "perdita di memoria" viene ripetuta più volte, una possibile situazione in cui tutta la memoria disponibile nel computer verrà "occupata". Ciò porterà a conseguenze imprevedibili per il sistema operativo.

7. Come allocare memoria usando il nuovo operatore con l'intercettazione di una situazione critica in cui la memoria non può essere allocata? Eccezione bad_alloc. Esempio

Quando si utilizza il nuovo operatore, è possibile che la memoria non venga allocata. La memoria non può essere allocata nelle seguenti situazioni:

  • se non c'è memoria libera;
  • la dimensione della memoria libera è inferiore a quella specificata nel nuovo operatore.

In questo caso, viene generata un'eccezione bad_alloc. Il programma può rilevare questa situazione e gestirla di conseguenza.

Esempio. L'esempio tiene conto della situazione in cui la memoria non può essere allocata dal nuovo operatore. In questo caso, viene effettuato un tentativo di allocare memoria. Se il tentativo ha esito positivo, il programma continua. Se il tentativo fallisce, la funzione termina con il codice -1.

int main () ( // dichiara una matrice di puntatori a float float * ptrArray; provare ( // tenta di allocare memoria per 10 float ptrArray \u003d nuovo float; ) catch (bad_alloc ba) (cout<< << endl; cout << ba.what() << endl; return -1; // esce dalla funzione } // se tutto è a posto, usa un array per (int i \u003d 0; i< 10; i++) ptrArray[i] = i * i + 3; int d = ptrArray; cout << d << endl; delete ptrArray; // libera la memoria allocata per l'array ritorna 0; )
8. Allocazione della memoria per una variabile con inizializzazione simultanea. Forma generale. Esempio

L'operatore di allocazione nuovo per una singola variabile consente l'inizializzazione simultanea con il valore di quella variabile.

In generale, l'allocazione di memoria per una variabile con inizializzazione simultanea è del modulo

ptrName\u003d nuovo tipo ( valore)
  • ptrName- il nome della variabile puntatore per cui è allocata la memoria;
  • genere - il tipo a cui punta il puntatore ptrName ;
  • valore - il valore impostato per l'area di memoria allocata (valore tramite puntatore).

Esempio. Allocazione della memoria per variabili con inizializzazione simultanea. Di seguito è la funzione main () per un'applicazione console. Viene dimostrata l'allocazione della memoria con l'inizializzazione simultanea. La situazione viene presa in considerazione anche quando un tentativo di allocare memoria fallisce (situazione critica bad_alloc).

#include "stdafx.h" #include usando lo spazio dei nomi std; int main () ( // allocazione della memoria con inizializzazione simultanea float * pF; int * pI; char * pC; provare ( // prova ad allocare memoria per variabili con inizializzazione simultanea pF \u003d new float (3.88); // * pF \u003d 3.88 pI \u003d new int (250); // * pI \u003d 250 pC \u003d nuovo carattere ("M"); // * pC \u003d "M") catch (bad_alloc ba) (cout<< Eccezione: nessuna memoria allocata << endl; cout << ba.what() << endl; return -1; // esce dalla funzione } // se la memoria è allocata, quindi usando i puntatori pF, pI, pC float f \u003d * pF; // f \u003d 3.88 int i \u003d * pI; // i \u003d 250; char c; c \u003d * pC; // c \u003d "M" // visualizza i valori inizializzati cout<< "*pF = " << f<< endl; cout << "*pI = " << i << endl; cout << "*pC = " << c << endl; // memoria libera precedentemente allocata per i puntatori elimina pF; elimina pI; elimina pC; ritorna 0; )

Abbiamo scoperto le possibilità di allocazione dinamica della memoria. Cosa significa? Ciò significa che con l'allocazione dinamica della memoria, la memoria è riservata non in fase di compilazione ma in fase di esecuzione del programma. E questo ci dà la possibilità di allocare la memoria in modo più efficiente, principalmente per gli array. Con l'allocazione dinamica della memoria, non è necessario impostare anticipatamente la dimensione dell'array, soprattutto perché non è sempre noto quale dimensione dell'array dovrebbe avere. Quindi, vediamo come è possibile allocare memoria.

Allocazione di memoria in C (funzione malloc)

La funzione malloc () è definita nel file di intestazione stdlib.h, viene utilizzata per inizializzare i puntatori con la quantità di memoria richiesta. La memoria viene allocata da un settore di RAM disponibile per tutti i programmi in esecuzione su una determinata macchina. L'argomento è il numero di byte di memoria da allocare, la funzione ritorna - un puntatore al blocco allocato in memoria. La funzione malloc () funziona esattamente come qualsiasi altra funzione, niente di nuovo.

Poiché diversi tipi di dati hanno requisiti di memoria diversi, in qualche modo dobbiamo imparare come ottenere la dimensione in byte per diversi tipi di dati. Ad esempio, abbiamo bisogno di un pezzo di memoria per un array di valori int: questa è una dimensione di memoria e se abbiamo bisogno di allocare memoria per un array della stessa dimensione, ma già del tipo char, questa è una dimensione diversa. Pertanto, è necessario in qualche modo calcolare la dimensione della memoria. Questo può essere fatto con l'operazione sizeof (), che accetta un'espressione e ne restituisce le dimensioni. Ad esempio, sizeof (int) restituirà il numero di byte richiesti per memorizzare un int. Consideriamo un esempio:

#includere int * ptrVar \u003d malloc (sizeof (int));

In questo esempio, in linea 3 al puntatore ptrVar viene assegnato un indirizzo a una posizione di memoria le cui dimensioni corrispondono al tipo di dati int. Automaticamente, questa area di memoria diventa inaccessibile ad altri programmi. Ciò significa che dopo che la memoria allocata diventa superflua, deve essere esplicitamente rilasciata. Se la memoria non viene esplicitamente rilasciata, quindi al termine del programma, la memoria non verrà liberata per il sistema operativo, questo si chiama perdita di memoria. Puoi anche determinare la dimensione della memoria allocata da allocare passando un puntatore nullo, ecco un esempio:

Int * ptrVar \u003d malloc (sizeof (* ptrVar));

Cosa sta succedendo qui? L'operazione sizeof (* ptrVar) stimerà la dimensione del blocco di memoria a cui fa riferimento il puntatore. Poiché ptrVar è un puntatore a un pezzo di memoria di tipo int, sizeof () restituirà la dimensione di un numero intero. Cioè, essenzialmente, basato sulla prima parte della definizione del puntatore, viene calcolata la dimensione per la seconda parte. Allora perché ne abbiamo bisogno? Ciò può essere necessario se improvvisamente è necessario modificare la definizione di un puntatore, int, ad esempio, in virgola mobile, quindi non è necessario modificare il tipo di dati in due parti della definizione del puntatore. Basterà cambiare la prima parte:

Float * ptrVar \u003d malloc (sizeof (* ptrVar));

Come puoi vedere, c'è un lato molto forte in questa notazione, non dovremmo chiamare la funzione malloc () usando sizeof (float). Invece, abbiamo passato un puntatore al tipo float a malloc (), nel qual caso la dimensione della memoria allocata sarà automaticamente determinata da sola!

Ciò è particolarmente utile se è necessario allocare memoria lontano dalla definizione del puntatore:

Float * ptrVar; / *. ... ... cento righe di codice * /. ... ... ptrVar \u003d malloc (sizeof (* ptrVar));

Se hai usato la costruzione dell'allocazione di memoria con l'operazione sizeof (), allora dovresti trovare la definizione di un puntatore nel codice, guardare il suo tipo di dati e solo allora sarai in grado di allocare correttamente la memoria.

Liberare memoria allocata

La memoria viene liberata usando la funzione free (). Ecco un esempio:

Gratuito (ptrVar);

Dopo aver liberato memoria, è buona norma reimpostare il puntatore su zero, ovvero assegnare * ptrVar \u003d 0. Se al puntatore viene assegnato 0, il puntatore diventa , in altre parole, non punta più da nessuna parte. Sempre dopo aver rilasciato la memoria, assegna 0 al puntatore, altrimenti, anche dopo aver liberato la memoria, il puntatore lo punta ancora, il che significa che puoi danneggiare accidentalmente altri programmi che potrebbero utilizzare questa memoria, ma non ne sai nemmeno nulla imparerai e penserai che il programma funzioni correttamente.

PS: Chiunque sia appassionato di editing video potrebbe essere interessato a questo editor video di Windows 7. L'editor video si chiama Movavi, forse qualcuno lo conosce già o addirittura ci ha lavorato. Con questo programma in russo, puoi facilmente aggiungere video dalla fotocamera, migliorare la qualità e applicare bellissimi effetti video.

Prima di immergerci nello sviluppo orientato agli oggetti, dovremo fare una piccola digressione su come lavorare con la memoria in un programma C ++. Non possiamo scrivere programmi complessi senza essere in grado di allocare memoria in fase di esecuzione e accedervi.
In C ++, gli oggetti possono essere allocati staticamente in fase di compilazione o dinamicamente in fase di esecuzione chiamando le funzioni dalla libreria standard. La principale differenza nell'uso di questi metodi è la loro efficienza e flessibilità. L'allocazione statica è più efficiente perché la memoria viene allocata prima dell'esecuzione del programma, ma è molto meno flessibile perché dobbiamo conoscere in anticipo il tipo e la dimensione dell'oggetto da allocare. Ad esempio, non è affatto facile posizionare il contenuto di un file di testo in una matrice statica di stringhe: dobbiamo conoscerne le dimensioni in anticipo. Le attività che devono archiviare ed elaborare in anticipo un numero sconosciuto di elementi richiedono in genere l'allocazione dinamica della memoria.
Finora, tutti i nostri esempi hanno utilizzato l'allocazione di memoria statica. Diciamo la definizione della variabile ival

Int ival \u003d 1024;

impone al compilatore di allocare un'area in memoria abbastanza grande da memorizzare una variabile int, associare il nome ival a quest'area e posizionare lì il valore 1024. Tutto questo viene fatto in fase di compilazione, prima che il programma venga eseguito.
All'oggetto ival sono associati due valori: il valore effettivo della variabile, 1024 in questo caso e l'indirizzo dell'area di memoria in cui è memorizzato questo valore. Possiamo fare riferimento a una di queste due quantità. Quando scriviamo:

Int ival2 \u003d ival + 1;

quindi ci riferiamo al valore contenuto nella variabile ival: aggiungiamo 1 ad essa e inizializziamo la variabile ival2 con questo nuovo valore, 1025. Come possiamo fare riferimento all'indirizzo al quale si trova la variabile?
C ++ ha un tipo di puntatore incorporato, che viene utilizzato per memorizzare gli indirizzi degli oggetti. Per dichiarare un puntatore contenente l'indirizzo della variabile ival, dobbiamo scrivere:

Int * pint; // puntatore a un oggetto di tipo int

Esiste anche un'operazione speciale per prendere un indirizzo, indicata dal simbolo &. Il risultato è l'indirizzo dell'oggetto. La seguente istruzione assegna l'indirizzo della variabile ival al puntatore pinta:

Int * pint; pint \u003d // pint ottiene il valore dell'indirizzo ival

Possiamo fare riferimento all'oggetto il cui indirizzo contiene pinta (ival nel nostro caso) usando l'operazione dereferenziazionechiamato anche indirizzamento indiretto... Questa operazione è indicata da *. Ecco come aggiungerne uno indirettamente a ival usando il suo indirizzo:

* pint \u003d * pint + 1; // aumenta implicitamente l'ivalente

Questa espressione fa esattamente la stessa cosa di

Ival \u003d ival + 1; // aumenta esplicitamente l'ivalente

Questo esempio non ha alcun senso: usare un puntatore per manipolare indirettamente la variabile ival è meno efficiente e meno descrittivo. Abbiamo incluso solo questo esempio per darti una comprensione di base dei puntatori. In realtà, i puntatori sono spesso usati per manipolare oggetti posizionati dinamicamente.
Le principali differenze tra allocazione di memoria statica e dinamica sono le seguenti:

  • gli oggetti statici sono designati da variabili nominate e le azioni su questi oggetti vengono eseguite direttamente usando i loro nomi. Gli oggetti dinamici non hanno i loro nomi e le azioni su di essi vengono eseguite indirettamente, usando i puntatori;
  • l'allocazione e la liberazione della memoria per gli oggetti statici viene eseguita automaticamente dal compilatore. Il programmatore non deve occuparsene da solo. Allocare e liberare memoria per oggetti dinamici è interamente responsabilità del programmatore. Questo è un compito difficile ed è facile commettere errori nel risolverlo. Gli operatori new ed delete vengono utilizzati per manipolare la memoria allocata dinamicamente.

Il nuovo operatore ha due forme. Il primo modulo alloca memoria per un singolo oggetto di un certo tipo:

Int * pint \u003d new int (1024);

Qui il nuovo operatore alloca memoria per un oggetto senza nome di tipo int, lo inizializza su 1024 e restituisce l'indirizzo dell'oggetto creato. Questo indirizzo viene utilizzato per inizializzare il puntatore pinta. Tutte le azioni su un tale oggetto senza nome vengono eseguite dereferenziando questo puntatore, da allora non è possibile manipolare esplicitamente un oggetto dinamico.
La seconda forma del nuovo operatore alloca memoria per un array di una determinata dimensione, costituito da elementi di un certo tipo:

Int * pia \u003d new int;

In questo esempio, la memoria è allocata per un array di quattro elementi int. Sfortunatamente, questa forma del nuovo operatore non consente l'inizializzazione di elementi dell'array.
Una certa confusione è causata dal fatto che entrambe le forme del nuovo operatore restituiscono lo stesso puntatore, nel nostro esempio è un puntatore a un numero intero. Sia pint che pia sono dichiarate esattamente uguali, ma pint indica un singolo int e pia indica il primo elemento di una matrice di quattro oggetti int.
Quando l'oggetto dinamico non è più necessario, dobbiamo liberare esplicitamente la memoria allocata per esso. Questo viene fatto usando l'operatore delete, che, come nuovo, ha due forme: per un singolo oggetto e per un array:

// rilascia un singolo oggetto delete pint; // libera l'array delete pia;

Cosa succede se dimentichiamo di liberare la memoria allocata? La memoria sarà sprecata, non sarà utilizzata, ma non può essere restituita al sistema perché non abbiamo un puntatore. Questo fenomeno ha ricevuto un nome speciale perdita di memoria... Alla fine, il programma si arresterà in modo anomalo a causa di memoria insufficiente (supponendo, ovviamente, funzionerà abbastanza a lungo). Una piccola perdita è difficile da rilevare, ma esistono utilità per aiutarti a farlo.
La nostra breve panoramica sull'allocazione dinamica della memoria e sull'utilizzo del puntatore ha probabilmente sollevato più domande di quelle a cui ha risposto. La sezione 8.4 tratterà le questioni sollevate in dettaglio. Tuttavia, non potremmo fare a meno di questa digressione, poiché la classe Array, che progetteremo nelle sezioni seguenti, si basa sull'uso della memoria allocata dinamicamente.

Esercizio 2.3

Spiega la differenza tra i quattro oggetti:

(a) int ival \u003d 1024; (b) int * pi \u003d (c) int * pi2 \u003d new int (1024); (d) int * pi3 \u003d new int;

Esercizio 2.4

Cosa fa il seguente codice? Qual è l'errore logico? (Si noti che l'operazione di acquisizione dell'indice () è correttamente applicata al puntatore pia. Una spiegazione di questo fatto è riportata nella Sezione 3.9.2.)

Int * pi \u003d new int (10); int * pia \u003d new int;
while (* pi< 10) {
pia [* pi] \u003d * pi; * pi \u003d * pi + 1;
) elimina pi; elimina pia;

Così. il terzo tipo, il più interessante in questo argomento per noi, è il tipo di memoria dinamica.

Come abbiamo lavorato con gli array prima? int a Come lavoriamo ora? Selezioniamo quanti ne abbiamo bisogno:

#includere < stdio.h> #includere < stdlib.h> int main () (size_t size; // Crea un puntatore a int // è essenzialmente un array vuoto. int * list; scanf ( "% lu", & taglia); // Alloca memoria per gli elementi size int // e il nostro "array vuoto" ora fa riferimento a questa memoria. list \u003d (int *) malloc (size * sizeof (int)); per (int i \u003d 0; i< size; ++i) { scanf ("% d" < size; ++i) { printf ("% d", * (elenco + i)); ) // Non dimenticare di ripulire dopo noi stessi! gratuito (elenco); ) // *

Void * malloc (size_t size);

Ma in generale, questa è una funzione che alloca byte di dimensioni di memoria non inizializzata (non zeri, ma immondizia).

Se l'allocazione ha esito positivo, viene restituito un puntatore al primo byte della memoria allocata.

In caso di esito negativo - NULL. Inoltre, errno eguaglierà ENOMEM (vedremo più avanti questa meravigliosa variabile). Cioè, era più corretto scrivere:

#includere < stdio.h> #includere < stdlib.h> int main () (size_t size; int * list; scanf ( "% lu", & taglia); list \u003d (int *) malloc (size * sizeof (int)); if (list \u003d\u003d NULL) (vai a errore;) per (int i \u003d 0; i< size; ++i) { scanf ("% d", elenco + i); ) per (int i \u003d 0; i< size; ++i) { printf ("% d", * (elenco + i)); ) gratuito (elenco); ritorna 0; errore: ritorno 1; ) // *

Non è necessario cancellare un puntatore NULL

#includere < stdlib.h> int main () (gratuito (NULL);)

- nello stesso clang tutto andrà bene (niente andrà bene), ma in casi più esotici potrebbe andare in crash il programma.

Accanto a malloc e gratuito in mana, puoi anche vedere:

    void * calloc (size_t count, size_t size);

    Oltre a malloc alloca memoria per oggetti conteggio di byte di dimensioni. La memoria allocata viene inizializzata con zeri.

    void * realloc (void * ptr, size_t size);

    Alloca nuovamente (se è possibile) la memoria indicata da ptr in byte di dimensioni. Se non c'è spazio sufficiente per aumentare la memoria allocata indicata da ptr, realloc crea una nuova allocazione, copia i vecchi dati indicati da ptr, libera la vecchia allocazione e restituisce un puntatore alla memoria allocata.

    Se ptr è NULL, realloc è identico a chiamare malloc.

    Se size è zero e ptr non è NULL, viene allocata la porzione di memoria minima della dimensione e quella originale viene liberata.

    void * reallocf (void * ptr, size_t size);

    Una nozione dall'API di FreeBSD. Come realloc, ma se non riesce a riassegnare, cancella il puntatore ricevuto.

    void * valloc (size_t size);

    Come malloc, ma la memoria allocata è allineata alla pagina.

Il programma può archiviare informazioni nella memoria principale di un computer in due modi principali. Il primo utilizza variabili globali e locali, tra cui array, strutture e classi. Nel caso di variabili locali globali e statiche, il percorso di archiviazione è fisso per l'intera durata dell'esecuzione del programma. Nel caso di variabili locali, la memoria viene allocata nello stack. Sebbene Borland C ++ implementi queste variabili in modo molto efficiente, il loro utilizzo richiede al programmatore di conoscere in anticipo la quantità di memoria che sarà richiesta durante l'esecuzione del programma.

Il secondo modo di archiviare le informazioni consiste nell'utilizzare il sistema di allocazione dinamica della memoria C ++ di Borland. In questo metodo, la memoria per l'archiviazione delle informazioni viene allocata dall'area di memoria libera secondo necessità e restituita, ad es. viene rilasciato quando il bisogno è scomparso. L'area della memoria libera si trova tra l'area della memoria in cui si trova il programma e lo stack. Questa area è chiamata heap e viene utilizzata per le richieste di heap.

Il vantaggio dell'utilizzo della memoria dinamica è che la stessa memoria può essere utilizzata per memorizzare informazioni diverse durante l'esecuzione del programma. Poiché la memoria viene allocata per uno scopo specifico e liberata al termine dell'utilizzo, è possibile utilizzare la stessa memoria in un momento diverso per scopi diversi in un'altra parte del programma. Un altro vantaggio dell'allocazione dinamica della memoria è la sua capacità di creare elenchi collegati, alberi binari e altre strutture di dati dinamici.

Il nucleo dell'allocazione dinamica della memoria C è malloc () e free (), che fanno parte della libreria standard. Ogni volta che una richiesta di allocazione della memoria viene effettuata da malloc (), viene allocata una porzione di memoria libera disponibile. Ogni volta che questa memoria viene liberata usando la funzione free (), questa memoria viene restituita al sistema.

Il linguaggio C ++ definisce due operatori di allocazione dinamica della memoria, new ed delete.

Lo standard ANSI C definisce solo quattro funzioni di allocazione dinamica della memoria: calloc (), malloc (), free () e realloc (). Tuttavia, Borland C ++ contiene diverse altre funzionalità di allocazione dinamica della memoria. Quando si compila il codice per il moderno modello di memoria a 32 bit, la memoria è piatta e di solito vengono utilizzate solo quattro funzioni standard di allocazione della memoria.

Lo standard ANSI C specifica che le informazioni di intestazione richieste per l'allocazione dinamica della memoria sono contenute nel file stdlib.h. Borland C ++, tuttavia, consente di utilizzare le intestazioni stdlib.h o alloc.h. Usiamo il file di intestazione stdlib.h qui perché fornisce portabilità. Alcune altre funzioni di allocazione dinamica della memoria richiedono i file di intestazione alloc.h, malloc.h o dos.h. È necessario prestare particolare attenzione a quale file di intestazione è necessario per utilizzare ciascuna funzione.

LA CAMPANA

C'è chi legge questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vuoi leggere The Bell
Niente spam