Log in

View Full Version : Help C++ Return Reference



Hardcore
11th May 2011, 10:06
Per un qualche motivo misterioso, all'ultimo anno di ing han deciso che è vitale che sappia il c++, ergo arrivando da 4 anni di Java è una menata.

C'è una cosa che mi rimane ancora misteriosa ed è il concetto di reference, soprattutto quando è nel return value.


template <typename _T> class image{

unsigned _w,_h;
vector <_T> _pixels;
public:
image (unsigned w=0,unsigned h=0) :_w(w),_h(h),_pixels(_w*_h){}

_T& operator () (unsigned x,unsigned y) {

return _pixels[(y*(_w-1)+x)-1];
}


Nel mio es il _T è un unsigned char, ergo quando faccio _pixels[blabla] ottengo un valore specifico di un unsigned char, ma cosa diavolo vuol dire che ritorno _T&, non mi è chiaro il &...

__________________________________________________ _________________

Altra cosa non chiara:

const _T& operator ()(unsigned x,unsigned y) const {

Per quale motivo ci sono due const?

San Vegeta
11th May 2011, 21:09
se non ricordo male, il reference è un puntatore a una locazione di memoria.
restituire un reference a un valore significa che chi si salva quel valore nella variabile ref_a, ha un puntatore alla locazione di memoria dove è salvato il valore: ogni modifica a quel valore si riflette nella variabile ref_a.
Edit: dimenticavo che il reference, una volta inizializzato, non puo' essere riassegnato: questa caratteristica, insieme al fatto che viene utilizzato come una normale variabile, lo rende differente dai puntatori

il secondo quesito non me lo ricordo, sorry

Dr.Doomed
12th May 2011, 00:37
...
__________________________________________________ _________________

Altra cosa non chiara:

const _T& operator ()(unsigned x,unsigned y) const {

Per quale motivo ci sono due const?

Il primo const si riferisce al valore ritornato, di fatto dicendoti che ritorna un valore costante che non puo` essere modificato, mentre il secondo const si riferisce alla funzione e serve per evidenziare come la funzione non puo` modificare i valori delle variabili di classe.
http://duramecho.com/ComputerInformation/WhyHowCppConst.html

Hardcore
12th May 2011, 01:07
se non ricordo male, il reference è un puntatore a una locazione di memoria.
restituire un reference a un valore significa che chi si salva quel valore nella variabile ref_a, ha un puntatore alla locazione di memoria dove è salvato il valore: ogni modifica a quel valore si riflette nella variabile ref_a.
Edit: dimenticavo che il reference, una volta inizializzato, non puo' essere riassegnato: questa caratteristica, insieme al fatto che viene utilizzato come una normale variabile, lo rende differente dai puntatori

il secondo quesito non me lo ricordo, sorry

ok, ma quindi se mettiamo che io volessi poter accedere a tale valore dalla funzione main, devo usare una variabile puntatore?

cioè se faccio:




class prova{

int _a;

public:

prova(): _a(0){}

int & get_a(){

return a;
}

};

void main(){

prova test;

int* a1=test.get_a();

int a2=test.get_a();

}




se lavoro con a1 modifico a della classe, mentre se lavoro con a2, vado a modificarne una copia con scope solo nel main? ho capito bene?

San Vegeta
12th May 2011, 08:44
non devi usare un puntatore, devi usare un reference.

se non erro la sintassi è

ref int a = test.get_a();

marlborojack
12th May 2011, 19:17
template <typename _T> class image{

unsigned _w,_h;
vector <_T> _pixels;
public:
image (unsigned w=0,unsigned h=0) :_w(w),_h(h),_pixels(_w*_h){}

_T& operator () (unsigned x,unsigned y) {

return _pixels[(y*(_w-1)+x)-1];
}

[/QUOTE]

Ridefinendo un operatore devi ritornare un valore sinistro, perchè l'operatore in pratica viene chiamato sull'oggetto this della classe come parametro formale. In questo modo quello che viene chiamata è l'istanza dell'oggetto this e viene ritornato l'oggeto stesso modificato. Se tu non usassi un riferimento &, ritorneresti una copia dell'oggetto this, ovvero una nuova istanza senza modificare l'oggetto sul quale chiami il metodo.


__________________________________________________ _________________

Altra cosa non chiara:

const _T& operator ()(unsigned x,unsigned y) const {

Per quale motivo ci sono due const?

ritorna un riferimento costante (primo const), perchè il metodo ritorna this come oggetto non modificabile, ovvero come riferimento costante. Il metodo in sè stesso poi è costante, nel senso che ritorna un'instanza costante. Se così non fosse, paradossalmente potresti scrivere qualcosa tipo
(a + b) (normalmente un valore destro, per i tipi base, quindi non assegnabile a sinistra) = c (assegnare un valore destro a quello che dovrebbe essere un valore destro ma in realtà lo rendi un valore sinistro senza il secondo const), ovvero assegnare al riferimento a this ritornato dal template un nuovo valore mandando un vacca l'organizzazione ad oggetti.

Se questi concetti non ti sono chiari però ti consiglio di dare una lettura allo Stroustrup, altrimenti chiedi pure

Eltarion
12th May 2011, 22:33
arrivo in ritardo ma quoto marlboro :P

marlborojack
12th May 2011, 23:29
:P

Comunque questo esempio è un casino, perchè la sintassi è complicata dal template. Cerco di spiegarmi meglio:

Con i template definisci oggeti che non dipendono dalla rappresentazione, nel caso specifico l'immagine, per memorizzata che sia, deve essere istanziata con le proprietà di altezza e lunghezza. Il template serve a farti eseguire le operazioni definendo in seguito la rappresentazione, nel tuo caso un tipo_pixels mi pare di capire, che sarà a occhio un array di pixels, che da solo non manterrebbe l'informazioni senza imporre l'interfaccia data dal template.

Quando dichiari un oggetto Image in questo caso metti tra le angolate l'oggetto al quale l'interfaccia, in questo modo a tempo di esecuzione istanzi dei metodi su di un certo tipo e nel contempo a livello di scrittura del codice puoi utilizzare i metodi. Di più, in C++ puoi definire i tipi ma soprattutto ridefinire gli operatori, che sono costrutti più complessi perchè sono binari: è previsto infatti un operando sinistro ed un operando destro.

Gli operatori dei tipi base devono eseguire il risultato dell'operazione e ritornare il valore destro; per scriverlo in c++, si dice

funzione che ritorna iun oggetto del tipo definito come valore destro (ovvero un'area di memoria non modificabile che può essere assegnata ad un valore sinistro)



const _T&

col & gli dici di ritornare un'area di memoria già instanziata (il risultato della chiamata del costruttore), con _T gli dichiari il tipo da ritornare e con const imponi che non sia modificabile il riferimento in sè (ovvero se in qualche chiamata cerco di modificarlo ottengo un errore di compilazione), ma devi anche esprimere il fatto che l'oggetto in sè non è modificabile. da cui il secondo const che indica che l'oggetto in sè non può essere modificato. Infatti, non è possibile chiamare i metodi di un valore destro. Quindi

funzione che ritorna un oggetto del tipo definito come valore destro (ovvero un'area di memoria non modificabile che può essere assegnata ad un valore sinistro)



const _T& () const {


in sostanza

La classe immagine opera su un tipo generico


template <typename _T> class image{

memorizza due interi con lunghezza e altezza


unsigned _w,_h;

ma i pixel possono essere rappresentati da un oggetto generico.
L'immagine è comunque un vettore di questi pixels


vector <_T> _pixels;

Costruisco un'immagine con una lista d'inizializzazione, ovvero chiamando i costruttori propri dei membri


public:
image (unsigned w=0,unsigned h=0) :_w(w),_h(h),_pixels(_w*_h){}

Faccio in modo che se chiamo immagine(x,y) mi sia ritornato il pixel corrispondente
ritornando il tipo generico (templetizzato) alla posizione interna del vettore. La rappresentazione interna dell'immagine è un vettore di righe * colonne pixels, ritorno quello
alla posizione bidimensionale x, y;


_T& operator () (unsigned x,unsigned y) {

return _pixels[(y*(_w-1)+x)-1];
}


Il pixel non lo posso modificare, così come non posso scrivere immagine(x,y) = c (errore a tempo di compilazione)

Eltarion
12th May 2011, 23:51
adesso però te la stai tirando eh!! :sneer: :sneer:

scherzo, ottima spiegazione ;)

Hardcore
13th May 2011, 00:07
_T& operator () (unsigned x,unsigned y) {

return _pixels[(y*(_w-1)+x)-1];
}


Il pixel non lo posso modificare, così come non posso scrivere immagine(x,y) = c (errore a tempo di compilazione)

In primis grazie per la spiegazione, molto chiara :)

Unica cosa che nn ho capito è questa.
Per quale motivo dici che nn posso modificarlo?
Qui non ritorna un const,e quindi dovrei poter modificarlo,lo scopo di questa funzione è proprio questo

marlborojack
13th May 2011, 08:20
In primis grazie per la spiegazione, molto chiara :)

Unica cosa che nn ho capito è questa.
Per quale motivo dici che nn posso modificarlo?
Qui non ritorna un const,e quindi dovrei poter modificarlo,lo scopo di questa funzione è proprio questo
Pensavo alla seconda richiesta che hai fatto con i const e lì per lì non ho notato che nel codice poi non c'erano :sneer: comunque penso tu abbia capito, visto che giustamente me l'hai fatto notare.