Questo tipo di memoria viene allocato nell'heap o nello stack?
-
06-07-2019 - |
Domanda
Nel contesto di C ++ (non è importante):
class Foo{
private:
int x[100];
public:
Foo();
}
Quello che ho imparato mi dice che se crei un'istanza di Foo in questo modo:
Foo bar = new Foo();
Quindi l'array x viene allocato sull'heap, ma se hai creato un'istanza di Foo in questo modo:
Foo bar;
Quindi viene creato nello stack.
Non riesco a trovare risorse online per confermarlo.
Soluzione
Data una leggera modifica del tuo esempio:
class Foo{
private:
int x[100];
int *y;
public:
Foo()
{
y = new int[100];
}
~Foo()
{
delete[] y;
}
}
Esempio 1:
Foo *bar = new Foo();
- xey sono nell'heap:
- sizeof (Foo *) viene creato nello stack.
- sizeof (int) * 100 * 2 + sizeof (int *) è nell'heap
Esempio 2:
Foo bar;
- x è nello stack e y è nell'heap
- sizeof (int) * 100 è nello stack (x) + sizeof (int *)
- sizeof (int) * 100 è nell'heap (y)
Le dimensioni effettive possono differire leggermente a causa dell'allineamento di classe / struttura a seconda del compilatore e della piattaforma.
Altri suggerimenti
A rigor di termini, secondo lo standard, l'oggetto non deve necessariamente esistere su una pila o un mucchio. Lo standard definisce 3 tipi di "durata della memoria", ma non specifica esattamente come deve essere implementata la memoria:
- durata dell'archiviazione statica
- durata della memorizzazione automatica
- durata della memoria dinamica
La durata della memorizzazione automatica è in genere (quasi sempre) implementata utilizzando lo stack.
La durata della memorizzazione dinamica viene in genere implementata utilizzando l'heap (in definitiva tramite malloc ()
), sebbene ciò possa essere sovrascritto anche dall'utente del compilatore.
La durata dell'archiviazione statica è ciò che è comunemente noto come globale (o archiviazione statica).
Lo standard ha questo da dire su queste cose (i seguenti sono estratti da vari bit di 3.7 - Durata della memorizzazione):
Durata di archiviazione statica e automatica sono associati agli oggetti introdotti dalle dichiarazioni (3.1) e implicitamente creato dall'implementazione (12.2). La durata della memoria dinamica è associato ad oggetti creati con operatore nuovo (5.3.4).
...
Tutti gli oggetti che non hanno nessuno dinamico durata di conservazione né locale durata dell'archiviazione statica. Lo stoccaggio per questi oggetti deve durare per il durata del programma (3.6.2, 3.6.3).
...
Gli oggetti locali dichiarati esplicitamente auto o registrati o non esplicitamente dichiarato statico o esterno hanno automatico durata di conservazione. Lo spazio di archiviazione per questi oggetti durano fino al blocco da cui vengono creati esce.
...
Gli oggetti possono essere creati dinamicamente durante l'esecuzione del programma (1.9), usando nuove espressioni (5.3.4) e distrutte usando delete-expressions (5.3.5). CORRENTE ALTERNATA + + l'implementazione fornisce l'accesso e la gestione dell'archiviazione dinamica tramite le funzioni di allocazione globale operatore nuovo e operatore nuovo [] e le funzioni di deallocazione globale operator delete e operator delete [].
...
La libreria fornisce l'impostazione predefinita definizioni per l'allocazione globale e funzioni di deallocazione. Alcuni allocazione globale e deallocazione le funzioni sono sostituibili (18.4.1)
E infine (per quanto riguarda l'array nella tua classe di esempio):
3.7.4 Durata degli oggetti secondari [basic.stc.inherit]
La durata di archiviazione degli oggetti secondari, degli oggetti secondari della classe base e degli elementi dell'array è quella del loro completo oggetto (1.8).
Un oggetto di tipo Foo prende la dimensione di 100 in memorizzata in sequenza. Se lo crei nello stack, otterrai tutto nello stack. Se lo fai con nuovi, sarà sull'heap come parte dell'oggetto.
Fa parte delle specifiche del linguaggio, non sono sicuro di quale sia la tua domanda.
Sì, l'array membro x
verrà creato sull'heap se si crea l'oggetto Foo
sull'heap. Quando si alloca memoria dinamica per Foo
si richiede memoria di lunghezza sizeof (Foo)
(più eventualmente un sovraccarico di memoria, ma per il momento ignorarlo), che per il momento) nel tuo codice di esempio implica la dimensione di 100 int
s. Questo deve essere valido per la durata della vita di oggetti di tipo Foo
(e relativi dati interni) per attraversare gli ambiti.
Se non si crea l'oggetto Foo
sull'heap e l'array interno di Foo
non è un puntatore a cui si alloca memoria con nuovo
nel costruttore di Foo
, allora quell'array interno verrà creato nello stack. Ancora una volta, questo deve essere il caso affinché l'array venga pulito automaticamente senza delete
s al termine dell'ambito. In particolare,
struct Foo {
int* y;
Foo() : y(new int()) { }
~Foo() { delete y; }
};
creerà y
sull'heap indipendentemente dal fatto che un oggetto Foo
sia stato creato sullo stack o sull'heap.
Intendi
Foo* bar = new Foo();
Suppongo. Quello viene creato nell'heap.