2016-06-22 49 views
9

Considerate questo codice:Il collegamento di un riferimento effettivamente valuta l'operando?

int& x=*new int; 

fa RHS della cessione in realtà dereference il puntatore appena creato, che porta a UB a causa di lettura variabile non inizializzata? Oppure può essere legittimamente utilizzato per assegnare successivamente un valore come x=5;?

+2

Questo è un codice legittimo e sicuro finché si inizializza 'x' successivamente con qualche valore, piuttosto che consumare la variabile non inizializzata per qualche scopo. La cosa migliore sarebbe 'int & x = * new int()' che lo inizializza anche a zero. E naturalmente devi eliminare la memoria allocata. – Arunmu

+4

Non penso che sia diverso da 'int y; int & x = y; ', che è ciò che accade nel modo in cui si fa' int y; std :: cin >> y; ' – dyp

risposta

6

Per quanto ne so, nessuno di ciò che hai fatto comporta un comportamento indefinito.

Tuttavia, crea immediatamente un rischio di perdita di memoria. Può essere risolto rapidamente (poiché &x si risolverebbe all'indirizzo della memoria trapelata e può quindi essere eliminato) ma se si dovesse lasciare l'ambito, non si avrebbe alcun modo di recuperare quel puntatore.

Edit: al punto, se si dovesse scrivere

int& x=*new int; 
x = 5; 

std::cout << x << std::endl; 

std::cin >> x; 

std::cout << x << std::endl; 

Il codice si comporterebbe come se si fosse semplicemente dichiarato x come int x;, tranne che il puntatore sarebbe anche lasciato in sospeso dopo che il programma è terminato ambito .

Si otterrebbe un comportamento non definito se si tentasse di leggere la variabile non inizializzata prima di assegnargli un valore, ma ciò non sarebbe falso se lo stack x fosse allocato.

+1

@BenjaminLindley Rivisitato il linguaggio per dire" creare un * rischio * di una perdita di memoria ". E la ragione per cui la sto chiamando una perdita di memoria è che, da solo, il codice stesso non contiene un puntatore visibile all'utente alla memoria. – Xirema

0

Non consiglierei di farlo. Aliasing memoria dinamica con una variabile che sembra statico mi sembra pericoloso. Si consideri il seguente codice

#include <iostream> 

int* dynamicAlloc() { 
    int& x = *new int; 
    std::cout << "Inside dynamicAlloc: " << x << std::endl; 
    std::cout << "Modified: " << (x = 1) << std::endl; 
    return &x; 
} 

int main() { 
    int *dall = dynamicAlloc();; 

    std::cout << "dall (address): " << dall << std::endl; 
    std::cout << "dall -> " << *dall << std::endl; // Memory not cleaned 

    delete dall; // Don't forget to delete 

    return 0; 
} 

ottengo output come questo:

Inside dynamicAlloc: -842150451 
Modified: 1 
dall (address): 00F642A0 
dall -> 1 

Si noti come dereferenziazione dall non si traduca in un segfault. Non è stato deallocato quando x è caduto dal campo di applicazione. Altrimenti si sarebbe probabilmente verificato un segfault.

In conclusione:

int& x fa x un alias per la memoria allocata dinamicamente. È possibile modificare legittimamente quella memoria, ma non eseguirà la ripulitura poiché cade fuori dall'ambito e porta automaticamente a potenziali perdite di memoria.

+0

Non capisco. Ovviamente non puoi usare un puntatore dopo che è stato cancellato. L'unico rischio per gli OP è che se la memoria non viene gestita correttamente potrebbe perdere. – NathanOliver

+0

Lo scopo principale era dimostrare che l'indirizzo non è de-allocato dopo che 'x' cade fuori ambito in' test() '. In seguito potresti cancellare 'x' se gestisci le cose correttamente, ma non è intuitivo. Prenderò in considerazione come re-word una volta che sono fuori dal lavoro – Assimilater

+0

Speriamo che la formulazione sia leggermente migliore ora – Assimilater