2011-01-07 16 views
13

A C++ domanda,Cosa int & media

so

int* foo(void) 

foo sarà restituire un puntatore a int tipo

come su

int &foo(void) 

cosa fa ritorno ?

Grazie mille!

+0

Buono a sapersi: http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c –

risposta

1

Restituisce un riferimento a una variabile int.

+0

Non è necessario che sia una variabile (che implica che sia denominata) . Restituisce un riferimento a un oggetto int. –

27

Restituisce un riferimento a un int. I riferimenti sono simili ai puntatori ma con alcune importanti distinzioni. Ti consiglierei di leggere le differenze tra puntatori, riferimenti, oggetti e tipi di dati primitivi.

"Efficace C++" e "Più efficace C++" (entrambi di Scott Meyers) hanno alcune buone descrizioni delle differenze e quando utilizzare i puntatori contro i riferimenti.

MODIFICA: ci sono un certo numero di risposte che dicono cose del tipo "i riferimenti sono solo zucchero sintattico per una più facile gestione dei puntatori". Sicuramente sono non.

consideri il codice seguente:

int a = 3; 
int b = 4; 
int* pointerToA = &a; 
int* pointerToB = &b; 
int* p = pointerToA; 
p = pointerToB; 
printf("%d %d %d\n", a, b, *p); // Prints 3 4 4 
int& referenceToA = a; 
int& referenceToB = b; 
int& r = referenceToA; 
r = referenceToB; 
printf("%d %d %d\n", a, b, r); // Prints 4 4 4 

La linea p = pointerToB cambia il valore di p, cioè esso ora punta a un diverso pezzo di memoria.

r = referenceToB fa qualcosa di completamente diverso: assegna il valore di a dove era il valore di a. Lo fa non cambia r affatto. r è ancora un riferimento allo stesso pezzo di memoria.

La differenza è sottile ma molto importante.

Se si pensa ancora che i riferimenti siano solo zucchero sintattico per la gestione del puntatore, quindi per favore leggere i libri di Scott Meyers. Lui può spiegare la differenza molto meglio di me.

+1

+1 per i libri di Scott Meyers. Must-have per chiunque voglia avere una buona conoscenza del C++. – Matthieu

+1

Sì, sono entrambi libri eccellenti. Mi ha insegnato tutto ciò che so! –

+0

Le variabili di riferimento sono quindi una sintassi alternativa per i puntatori * const *. – Bento

0

Questa domanda non è C/C++, poiché C non ha riferimenti, solo puntatori. Un int & è un riferimento a un int. Inoltre, non è necessario void, può essere solo int& foo();

+0

Questo è ciò che il documento dice, complementi del compilatore C/C++ TMS320C28x dello strumento Texas, http://focus.ti.com/lit/ug/spru514c/spru514c.pdf, pagina 122, int & __ byte (int, unsigned int), immagino sia diverso dal PC –

+0

@Alfred: No, non proprio. I linguaggi C e C++ non hanno versioni incorporate speciali. Il manuale è sbagliato, e questo è praticamente tutto. – Puppy

+0

@Alfred Zhong. No, la documentazione dice lo stesso di tutti gli altri qui. –

0

solo giocando con le variabili visualizzare il significato

int i = 5; 
int * pI = &i; 
int & referenceToI = * pI; 
referenceToI = 4; // now i == 4 

EDIT: I riferimenti sono solo zucchero sintattico per una più facile gestione puntatori. a livello di assembly, il codice generato dal compilatore restituisce a un indirizzo un puntatore

+0

Grazie! Lo so. Ciò che mi confonde è quando viene usato nella dichiarazione di funzione, come int & foo (...), cosa restituisce la funzione? –

+0

Restituisce un riferimento a ciò che viene inserito dopo il 'return'. –

+0

Non c'è ritorno, penso che sia il linguaggio assembly al suo interno, array MOVB [byte_index] .LSB, src, non ho idea di cosa significhi –

3

Fai attenzione qui ... stai camminando sulla linea C/C++.C'è una distinzione abbastanza chiara ma non sempre appare così:

C++: questo spesso significa un riferimento. Ad esempio, si consideri:

void func(int &x) 
{ 
    x = 4; 
} 

void callfunc() 
{ 
    int x = 7; 
    func(x); 
} 

Come tale, C++ può passare dal valore o pass by reference.

C tuttavia non ha tale passaggio per funzionalità di riferimento. & significa "addressof" ed è un modo per formulare un puntatore da una variabile. Tuttavia, si consideri questo:

void func(int* x) 
{ 
    *x = 4; 
} 

void callfunc() 
{ 
    int x = 7; 
    func(&x); 
} 

Ingannevolmente simile, ma fondamentalmente diverso. Cosa stai facendo in C sta passando un copia del puntatore. Ora queste cose puntano ancora alla stessa area di memoria, quindi l'effetto è come un passaggio per riferimento in termini di memoria puntata, ma non è un riferimento passato. È un riferimento a un punto in memoria.

Prova questo (compilare come C):

#include <stdio.h> 

void addptr(int* x) 
{ 
    printf("Add-ptr scope 1:\n"); 
    printf("Addr: %p\n", x); 
    printf("Pointed-to-memory: %d\n", *x); 
    *x = *x + 7; 
    x++; 
    printf("Add-ptr scope 2:\n"); 
    printf("Addr: %p\n", x); 
    printf("Pointed-to-memory: %d\n", *x); 
} 

int main(int argc, char** argv) 
{ 
    int a = 7; 
    int *y = &a; 
    printf("Main-Scope 2:\n"); 
    printf("Addr: %p\n", y); 
    printf("Pointed-to-memory: %d\n", *y); 
    addptr(y); 
    printf("Main-Scope 2:\n"); 
    printf("Addr: %p\n", y); 
    printf("Pointed-to-memory: %d\n", *y); 
    return 0; 

} 

Se C aveva passare riferimento, l'indirizzo del puntatore in arrivo, quando modificato addptr dovrebbe riflettersi in main, ma non è. I puntatori sono ancora valori.

Quindi, C fa non hanno alcun passaggio per meccanismo di riferimento. In C++, questo esiste, ed è quello che significa & in argomenti di funzione, ecc.

Modifica: Forse ti starai chiedendo perché non riesco a fare questa dimostrazione in C++ facilmente. È perché non posso cambiare l'indirizzo del riferimento. Affatto. Da t his quite good guide to references:

How can you reseat a reference to make it refer to a different object?

No way.

You can't separate the reference from the referent.

Unlike a pointer, once a reference is bound to an object, it can not be "reseated" to another object. The reference itself isn't an object (it has no identity; taking the address of a reference gives you the address of the referent; remember: the reference is its referent).

In that sense, a reference is similar to a const pointer such as int* const p (as opposed to a pointer to const such as int const* p). But please don't confuse references with pointers; they're very different from the programmer's standpoint.

A richiesta, su riferimenti di ritorno:

#include <iostream> 

using namespace std; 

int& function(int f) 
{ 
    f=f+3; 
    return f; 
} 

int main(int argc, char** argv) 
{ 
    int x = 7; 
    int y; 
    y = function(x); 
    cout << "Input: " << x << endl; 
    cout << "Output:" << y << endl; 
    return 0; 
} 

Qualsiasi buon compilatore dovrebbe dare questo messaggio di avviso in qualche forma:

exp.cpp: 7: 11 : avviso: riferimento alla memoria stack associata alla variabile locale 'f' restituito

Cosa significa? Bene, sappiamo che gli argomenti della funzione vengono inseriti nello stack (nota: non in realtà su x64, entrano nei registri e poi nello stack, ma sono nello stack letteralmente su x86) e ciò che sta dicendo questo avviso è che creare un riferimento a tale un oggetto non è una buona idea, perché non è garantito che venga lasciato sul posto. Il fatto è che è solo fortuna.

Quindi cosa dà? Prova questa versione modificata:

#include <iostream> 

using namespace std; 

int& function(int& f) 
{ 
    f=f+3; 
    return f; 
} 

int main(int argc, char** argv) 
{ 
    int x = 7; 
    int y; 
    y = function(x); 
    cout << "Input: " << x << endl; 
    cout << "Output:" << y << endl; 
    return 0; 
} 

Esegui questa operazione e vedrai che entrambi i valori vengono aggiornati. Che cosa? Bene, entrambi si riferiscono alla stessa cosa e quella cosa viene modificata.

+1

Grazie mille! So in C & foo, e se foo è un int, sarà l'indirizzo di foo e può essere passato a int * type. Quello che mi confonde è quando viene usato nella dichiarazione delle funzioni, int & foo (...), cosa non significa? –

+0

"Quello che stai facendo in C è passare una copia del puntatore." No, non lo sei - stai passando il * valore * dell'indirizzo * * della variabile locale 'x' a' func' come argomento * puntatore *. A quel punto non ci sono altri suggerimenti, quindi non puoi copiarne uno. Nell'esempio C++ si passa una variabile 'x' a una funzione che utilizza un argomento * reference *, quindi ciò che si ottiene è un riferimento a' x'. L'implementazione di questi è (probabilmente) la stessa: l'indirizzo di 'x' viene inserito nello stack. IOW C * fa * consente di utilizzare la semantica di riferimento, ma non fornisce la sintassi per supportarli. – dajames

+0

Sì, stai passando una * copia * del valore del puntatore - una * copia del puntatore *. Un puntatore è un indirizzo di memoria in sé e per sé (quindi una "variabile") contenente un altro indirizzo di memoria. Collega 'gdb' a un processo e sarai in grado di vederlo. Quindi l'atto di copiarlo è assegnare un nuovo spazio di memoria e inserire il valore. Questo è ciò che passa per valore. –

1

Dai commenti di Alfred

This is what the document says, Texas instrument's TMS320C28x C/C++ compiler intrinsics , page 122, int&__byte(int, unsigned int), I guess it is different from PC – Alfred Zhong

Dal manuale:

int &__byte(int *array, unsigned int byte_index);

MOVB array[byte_index].LSB, src

The lowest adressable unit in C28x is 16 bits. Therefore, normally you cannot access 8-bit MOVB dst, array[byte_index]. LSB entities off a memory location. This intrinsic helps access an 8-bit quantity off a memory location, and can be invoked as follows:

__byte(array,5) = 10;
b = __byte(array,20);

Questo significa solo che la funzione restituisce un riferimento a un intero che si comporta come una quantità di 8 bit. Poiché il valore è una modifica di riferimento, modificherà l'oggetto nella destinazione (proprio come l'istruzione MOVB), mentre l'assegnazione a b verrà copiata (proprio come MOVB) nella destinazione.

+0

Grazie Martin, sono confuso perché ho fatto esattamente come dice il manuale, __byte (array, 5) = 10, e il compilatore continua a lamentarsi "errore: l'espressione deve essere un lvalue modificabile" –