Credo che ci sia un po' di confusione su questo argomento anche per via dei nomi.
L'allocazione statica e l'allocazione locale sono 2 cose diverse in c++, l'allocazione dinamica della memoria è un'altra cosa ancora.
Inoltre una cosa è ciò che è definito sullo standard C++, un'altra è l'implementazione vera e propria che è lasciata al compilatore e dipende da architettura e S.O.
Sia l'allocazione locale ( Chiamata anche "su stack" perché in pratica sempre implementata con uno stack ) che l'allocazione dinamica ( chiamata "su heap" perché usa solitamente implementazioni specifiche del S.O. che usano un heap ), sono di solito entrambe definite dinamiche perché avvengono a runtime.
Quello che viene definito nello standard a seconda dei 3 casi è il ciclo di vita delle variabili, cioè fino a quando sono accessibili e quando viene chiamato il distruttore.
Le variabili statiche ( e.g. dichiarate fuori dal main in un file sorgente o dichiarate come "static" ) sono disponibili per tutto il ciclo di vita del programma, quando finisce il main viene chiamato il distruttore in ordine non ben definito.
Le variabili locali ( e.g. dichiarate dentro il main ) Sono valide dal momento della dichiarazione fino alla fine del blocco dove sono dichiarate. Alla fine del blocco viene chiamato il costruttore nell'ordine inverso di dichiarazione.
La memoria allocata dinamicamente ( con "new" ) non ha invece una variabile associata, il ciclo di vita è lasciato al programmatore che decide autonomamente quando chiamare la delete sul puntatore alla locazione di memoria. Anche se il programma finisce le delete e quindi i distruttori non verranno chiamati.
int * i = new int;
NB: Quando si fa questo, non abbiamo una variabile int allocata dinamicamente, abbiamo una variabile locale di tipo (int *) che punta a della memoria allocata dinamicamente, contigua, di dimensione del tipo int che sarà disponibile finchè non verrà chiamata la delete sul puntatore.
All'atto pratico, nelle implementazioni effettive del linguaggio, il vantaggio dell'utilizzare uno stack per le variabili locali è che l'allocazione non costa nulla e che non devi preoccuparti di distruggere gli oggetti. In pratica quando viene chiamata una funzione lo stack pointer della cpu aumenta del valore necessario a coprire la dimensione delle variabili locali, quando esce fa il contrario (più o meno, dipende dall'architettura ma è comunque molto veloce).
L'allocazione dinamica invece ha bisogno di routine più complesse di solito implementate dal sistema operativo attraverso un heap. Quando fai una new viene fatta una chiamata al s.o. che cerca un pezzo di memoria contiguo e libero dove ci stia tutta la memoria che hai chiesto. Questo può essere ordini di grandezza più lento che non allocare sullo stack.
Oltre a questo man mano che si alloca e si disalloca memoria sull'heap questo si frammenta rendendo più difficile trovare il posto per pezzi di memoria contigui. I S.O. moderni usano varie tecniche per mantenere deframmentata la memoria ma questo dipende appunto dall'implementazione.
Il problema non è dato dall'utilizzare ( leggere e scrivere sulla ) memoria dinamica ma l'atto di allocare e disallocare continuamente memoria. Anche perché, in pratica, si parla esattamente della stessa memoria eccetto che in architetture particolari.