2016-06-09 55 views
5

So che il riferimento non richiede alcuna memoria e punta alla stessa posizione di memoria a cui fa riferimento. per esempioDove viene memorizzata la variabile di riferimento

int i=10; 
int &r = a; 

Supponiamo i punti alla locazione di memoria 1000 quindi in questo caso r sarà anche punta alla posizione di memoria 1000. Ma in C++ quando mai ci dichiariamo una variabile la sua volontà ottiene memorizzare nella memoria in qualche luogo In questo caso r punta a qualche posizione ma dovrebbe essere memorizzato da qualche parte nella memoria come rappresentazione interna sul riferimento usa solo puntatore const. grazie in anticipo.

+2

Se r è una variabile, l'indirizzo di r è & r. Non è un riferimento, C non è C++. Quindi se r = & a, & r rappresenta l'indirizzo in cui è fornito l'indirizzo di a. – Tim

+0

'Dove viene memorizzata la variabile di riferimento' Questo non è specificato. –

risposta

6

Ciò non è specificato, e per una buona ragione. La vera risposta è: dipende dal riferimento. Può essere rappresentato come un normale puntatore o potrebbe non esistere affatto.

Se si dispone di un riferimento funzione-locale con durata di memorizzazione automatica, come questo r:

void foo() 
{ 
    int x[4] = {0, 1, 2, 3}; 
    int &r = x[1]; 
    // more code 
} 

allora probabilmente non occupa spazio a tutti. Il compilatore tratterà semplicemente tutti gli usi di r come alias per x[1] e accederà direttamente a int. Si noti che tali riferimenti alias possono anche derivare dalla funzione di inlining.

D'altra parte, se il riferimento è "persistente" o visibile ad altre unità di traduzione (come un membro dati o una variabile globale), deve occupare un po 'di spazio ed essere memorizzato da qualche parte. In tal caso, sarà probabilmente rappresentato come puntatore e il codice che lo utilizza verrà compilato per dereferenziare quel puntatore.

In teoria, sarebbero anche possibili altre opzioni (come una tabella di ricerca), ma non penso che siano utilizzate da alcun compilatore del mondo reale.

1

so che di riferimento non si assume alcuna memoria

Non

esattamente. Se un riferimento ha memoria, non è specificato. Potrebbe o potrebbe non esserlo. In questo particolare esempio, non ha bisogno di spazio di archiviazione, quindi in un'implementazione tipica non ne usa nessuno.

è punterà alla stessa posizione di memoria che si fa riferimento

Che suona come una tautologia o semplicemente un malinteso, a seconda di cosa si intende per "punto". Un riferimento si riferisce allo all'oggetto o è associato a all'oggetto. Puoi considerarlo un alias del nome della variabile. Il nome della variabile non usa neanche memoria.

In questo caso r sta puntando a qualche posizione, ma deve essere conservato da qualche parte nella memoria

Non è necessaria la conservazione in memoria.Considerate seguente codice:

int i=10; 
int &r = a; 
int j = r * 3; 

Il compilatore può interpretare come r * 3i * 3 come se si fosse scritto così, in primo luogo. La posizione dell'oggetto indicato è nota al momento della compilazione, quindi non è necessario memorizzare l'indirizzo in memoria, che è una cosa del tempo di esecuzione.

Ma, in altre situazioni, potrebbe essere necessario l'archiviazione. Ad esempio: si consideri un argomento di riferimento di una funzione non in linea con collegamento esterno. L'oggetto indicato non può essere conosciuto quando la funzione è compilata, quindi alcune informazioni devono essere passate in memoria, in fase di esecuzione.

come rappresentazione interna sull'uso riferimento const puntatore solo

Questo non è corretto. La rappresentazione interna potrebbe usare un puntatore, o potrebbe usare qualcos'altro, o potrebbe non aver bisogno di usare nulla.

Quindi, per rispondere in modo conciso

Da dove viene la variabile di riferimento viene memorizzato

E non è specificato. O da nessuna parte, o da qualche parte.

0

ciò che la norma dice:

E 'specificato se un riferimento richiede memorizzazione (3.7).

(C++ 11, [dcl.ref] ¶4)

Ciò significa che il compilatore è libero di scegliere su una base per-caso se non è richiesta alcuna memorizzazione.

Ora, lascia che la gente dica quello che vuole, ma i riferimenti si riducono a zucchero sintattico per i puntatori (anche a livello di compilatore, in tutti i principali compilatori C++ il concetto di "riferimento" scompare quasi subito dopo il frontend); quindi, nel caso generale possono aver bisogno del loro spazio in memoria, esattamente come fa un puntatore. Tuttavia, in casi come il tuo (riferimenti locali) il compilatore dovrebbe vedere attraverso di loro e ottimizzarli via se necessario.

Si noti tuttavia che questa non è un'esclusiva di riferimenti - il compilatore è in grado di eseguire questo stesso tipo di ottimizzazione anche tramite puntatori (una volta che il codice va in forma SSA non c'è nulla di speciale anche sul fatto che i riferimenti non possono essere reimpostati).

questo:

int glob; 

void direct() { 
    glob = 16; 
} 

void through_reference() { 
    int &a = glob; 
    a = 16; 
} 

void through_pointer() { 
    int *a = &glob; 
    *a = 16; 
} 

si riduce sempre lo stesso codice su qualsiasi compilatore ho provato sulla gcc.godbolt.org - example:

direct(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
through_reference(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
through_pointer(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
glob: 
     .zero 4 

D'altra parte, la situazione diventa un un po 'più scivoloso quando si parla di strutture; qui il compilatore può eliminare i riferimenti dall'attuale layout della struttura (se è in grado di ricostruire ciò a cui effettivamente puntano), mentre per i puntatori la situazione potrebbe essere un po 'più complicata (la loro elisione spezzerebbe le classi di layout standard cose).

In pratica, non ho mai visto questo tipo di ottimizzazione implementata in alcun compilatore del mondo reale. Prendi gcc o MSVC o Clang o qualsiasi altra cosa e vedrai sempre che la dimensione della struttura sarà uguale a even in the most trivial cases.

0

come rappresentazione interna sull'uso di riferimento const puntatore solo

Dove l'hai sentito? Quello non è vero.

Lo standard non specifica come vengono implementati i riferimenti.

Di seguito è eccessivamente semplificata

Più comunemente, il compilatore ha al suo interno una tabella di simboli dove memorizza tutte le informazioni necessarie sulle variabili.

Prendiamo un caso semplice:

int a; 
a = 100; 

quindi il compilatore può avere qualcosa di simile (per semplicità consente di fare l'indirizzo del a un indirizzo fisso noto)

| identifier | type | address | 
|------------|------|----------| 
| a   | int | 0xFF00A4 | 

Allora può tradursi il codice C++ in qualcosa del genere:

mov 0xFF00A4, 100 

Let ' s aggiungere un riferimento nel mix:

int a; 
a = 100; 
int& ra = 300; 

La tabella dei simboli il compilatore ha:

| identifier | type | address | 
|------------|------|----------| 
| a   | int | 0xFF00A4 | 
| ra   | int& | 0xFF00A4 | 

Oppure:

| identifier | type | address | alias | 
|------------|------|----------|-------| 
| a   | int | 0xFF00A4 | -  | 
| ra   | int& | -  | a  | 

e possono quindi generare il codice in questo modo:

mov 0xFF00A4, 100 
mov 0xFF00A4, 300 

Quando si dispone di un argomento di riferimento in una funzione, un puntatore viene passato internamente.

+0

Questo non è specifico per i riferimenti; I compilatori eseguono regolarmente questo tipo di ottimizzazione anche sui puntatori, una volta che tutto viene inserito nel modulo SSA non c'è davvero alcuna differenza. –