2013-06-13 8 views
9

Sto imparando su puntatori e riferimenti, e la mia domanda si riferisce a this spiegazione, in particolare la sezione seguente:Un riferimento crea una nuova posizione in memoria o un alias per una cella esistente?

Questo suggerisce che la dichiarazione int& ri = i crea una nuova cella di memoria, che ha un valore di &i ed esiste nella posizione di memoria sconosciuta.

Per verificare questa teoria, ho scritto un semplice caso, il risultato che si vede qui sotto:

enter image description here

Sono perplesso dal fatto che r e i hanno lo stesso indirizzo di memoria, che sembra contraddire le letture. Il risultato suggerisce che int& ri = i significa genericamente "creare un alias per la cella di memoria i e chiamarlo r" in modo che entrambi si riferiscano esattamente alla stessa cella.

Il documento è corretto o ho perso qualcosa?

+0

Non penso che sia un duplicato, mi sto chiedendo se il riferimento occupa effettivamente una cella nella memoria, non se tale indirizzo può essere ottenuto. C'è una differenza. – jesterII

+1

La domanda potrebbe non essere la stessa, ma penso che le risposte si applichino a questa. – juanchopanza

risposta

10

Da r è un riferimento ad i, tutte le operazioni sul r vengono trasformati dal compilatore in operazioni su i. Così facendo &r, ti dà l'indirizzo di memoria i.

(nota che a differenza dei puntatori, i riferimenti hanno la proprietà di non essere "rinviati" dopo dichiarato - fanno sempre riferimento alla stessa cosa - quindi non c'è modo per scrivere operazioni che funzionano "sul riferimento", non "su ciò che viene referenziato")

+0

Sarebbe possibile ottenere la posizione di memoria di 'r'? – jesterII

+9

@jesterII Non è nemmeno possibile porre la domanda. Non c'è alcuna garanzia che un riferimento abbia un indirizzo, può essere ottimizzato fuori dal compilatore (a differenza di un puntatore che deve essere da qualche parte) – Patashu

2

Il documento dice "Entrambi pi e ri contengono indirizzi che indicano la posizione di i, ma la differenza si trova in l'aspetto tra riferimenti e puntatori quando sono usati nelle espressioni. ", che è vero.

Hai scritto "[riferimento] genericamente" crea un alias per la cella di memoria i e chiamalo r "tale che entrambi si riferiscono esattamente alla stessa cella" che è anche vero.

Probabilmente hai frainteso il documento, hai ragione e lo è anche il documento.

0

Penso che this SO post possa essere di aiuto a voi. Citando una risposta data lì:

Un riferimento è un puntatore implicito. Fondamentalmente è possibile modificare il valore dei punti di riferimento ma non è possibile modificare il riferimento in modo che punti a altro.

Non sono sicuro di cosa intenda per "cella di memoria". Guardare il codice in assembly può aiutarti a capire la semantica di livello inferiore che si sta verificando. Poiché sembra che tu stia usando Windows, ti suggerirei, se sei abbastanza curioso, di eseguire la tua app in ollyDbg.

Il mio take (e potrei sbagliarmi) è che il compilatore considera pi un puntatore mutevole, mentre ri è un puntatore immutabile.

+1

Penso che in questo caso osservare l'assembly potrebbe essere confuso: il compilatore potrebbe richiedere archiviazione per implementare un riferimento in alcune circostanze e non in altri. Semanticamente, un riferimento è solo un alias, quindi non richiede alcuna memorizzazione di per sé. – juanchopanza

0

r è un riferimento indipendente (concetto) o solo un altro nome per i.Qualsiasi cambiamento venga fatto a uno di essi si rifletterà l'uno nell'altro.

7

C++ 11 §8.3.2/4

It is unspecified whether or not a reference requires storage. 

Dichiarando un riferimento lvalue (T&) si crea un alias concettuale per una posizione di memoria esistente. Il compilatore può utilizzare la regola "come se" per trattarla come desidera. Può creare un puntatore, può accedere direttamente alla memoria, ma non ti interessa come verrà implementato.

Il PDF che stai leggendo descrive una possibile implementazione di riferimenti lvalue, ma nel caso generale è sbagliato. Un buon modello mentale per i riferimenti lvalue darebbe un secondo nome alla stessa variabile, quindi è possibile accedere agli stessi dati tramite diversi nomi (e ambiti) diversi.

Inoltre, non è possibile prendere un indirizzo o creare un puntatore a rvalue, ma è possibile creare un riferimento di rvalue ad esso.

Problemi correlati