Memoria Stack vs Heap
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 12 di 104.
I programmi C++ usano due aree di memoria principali: lo stack e lo heap. Capire dove si trovano i tuoi oggetti è fondamentale per scrivere codice efficiente e privo di bug.
Lo stack è una memoria veloce e automatica. Le variabili dichiarate all'interno delle funzioni risiedono qui e vengono distrutte automaticamente quando escono dal loro ambito.
void example() {
int x = 10; // Allocazione sullo stack
Player player; // Allocazione sullo stack - distrutto automaticamente
} // x e player vengono distrutti quiLo heap è una memoria più grande ma più lenta che gestisci manualmente. Gli oggetti nell'heap persistono finché non li elimini esplicitamente.
void example() {
Player* player = new Player(); // Allocazione nell'heap
// player esiste finché non viene eliminato
delete player; // È necessaria la pulizia manuale
}Differenze principali:
| Stack | Heap |
|---|---|
| Allocazione rapida | Allocazione più lenta |
| Dimensioni limitate | Grande capacità |
| Pulizia automatica | È necessaria la pulizia manuale |
| Oggetti di dimensioni fisse | Oggetti di dimensioni dinamiche |
Usa l’allocazione nello stack per gli oggetti piccoli e di breve durata. Usa l’allocazione nell’heap quando gli oggetti devono sopravvivere al loro ambito o quando la loro dimensione è determinata in fase di esecuzione.
Dimenticare di eliminare la memoria heap causa perdite di memoria, una fonte comune di bug nei programmi C++.
Sfida
FacileEsploriamo la differenza tra la memoria stack e heap creando una semplice classe Counter che tiene traccia di quando gli oggetti vengono creati e distrutti.
Creerai due file per organizzare il codice:
Counter.h: Definisci una classeCountercon un attributo privatoname(stringa). Includi un costruttore che accetta un nome e stampa"Creating: <name>", e un distruttore che stampa"Destroying: <name>". Aggiungi un metodogetName()per restituire il nome del contatore.main.cpp: Mostra l'allocazione sia nello stack sia nell'heap. Leggi un nome dall'input, poi:- Crea un
Counterallocato nello stack usando quel nome - Crea un
Counterallocato nell'heap con il nome"HeapCounter" - Stampa i nomi di entrambi i contatori nel formato
"Stack: <name>"e"Heap: <name>" - Elimina il contatore allocato nell'heap per evitare una perdita di memoria
- Crea un
Osserva come i messaggi del costruttore e del distruttore compaiono in ordini diversi a seconda di quando crei ed elimini ciascun oggetto. L'oggetto nello stack verrà distrutto automaticamente quando termina main(), mentre l'oggetto nell'heap deve essere eliminato esplicitamente.
Includi il file header in main.cpp usando #include "Counter.h".
Provalo tu
#include <iostream>
#include <string>
#include "Counter.h"
using namespace std;
int main() {
// Leggi il nome dall'input
string inputName;
cin >> inputName;
// TODO: Crea un Counter allocato sullo stack usando inputName
// TODO: Crea un Counter allocato sull'heap con il nome "HeapCounter"
// TODO: Stampa il nome del Counter sullo stack nel formato "Stack: <name>"
// TODO: Stampa il nome del Counter sull'heap nel formato "Heap: <name>"
// TODO: Elimina il Counter allocato sull'heap per evitare una perdita di memoria
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore genericoEsercitati da solo: Compilatore C++ online