2011-12-05 19 views
25

Ho un vettore come membro di una classe e voglio restituire un riferimento ad esso tramite una funzione getVector(), in modo da poterlo modificare in seguito. Non è meglio praticare la funzione getVector() per essere const? Tuttavia ho ricevuto un errore "qualificatori caduti nel riferimento vincolante di tipo ..." nel seguente codice. Cosa dovrebbe essere modificato?Restituisce riferimento a una variabile membro vettoriale

class VectorHolder 
{ 
public: 
VectorHolder(const std::vector<int>&); 
std::vector<int>& getVector() const; 

private: 
std::vector<int> myVector; 

}; 

std::vector<int> &VectorHolder::getVector() const 
{ 
return myVector; 
} 

risposta

27

Poiché è una funzione membro const, il tipo di ritorno non può essere un riferimento non const. Make it const:

const std::vector<int> &VectorHolder::getVector() const 
{ 
    return myVector; 
} 

Ora va bene.

Perché va bene? Perché in una funzione membro const, il ogni membro diventa const in modo tale che non possa essere modificato, il che significa myVector è un vettore const nella funzione, che è il motivo per cui si deve fare il tipo di ritorno const pure, se restituisce il riferimento .

Ora è impossibile modificare lo stesso oggetto. Vedere che cosa si può fare e ciò che non può:

std::vector<int> & a = x.getVector();  //error - at compile time! 

const std::vector<int> & a = x.getVector(); //ok 
a.push_back(10);       //error - at compile time! 

std::vector<int> a = x.getVector();  //ok 
a.push_back(10);       //ok 

A proposito, mi chiedo il motivo per cui avete bisogno, VectorHolder, in primo luogo.

+0

in questo modo è quindi possibile modificare il vettore restituita in seguito dal codice in cui si restituirlo? – arjacsoh

+0

@arjacsoh: dipende. Vedi la modifica. – Nawaz

13

non è insolito per dichiarare entrambe le varianti const e mutevole, in questo modo:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; 
} 
const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; 
} 

il problema di fondo con il vostro programma è che ritorni un riferimento non-const da un metodo const.

std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << error: return mutable reference from const method 
} 

in modo da renderlo const utilizzando questo modulo:

const std::vector<int>& VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

e quando questo si trova in un metodo non const o il client contiene un riferimento non-const, allora si può legalmente utilizzare un non- metodo const:

std::vector<int>& VectorHolder::getVector() { 
    return myVector; // << ok 
} 

, infine, si potrebbe restituire un valore (in alcuni casi):

std::vector<int> VectorHolder::getVector() const { 
    return myVector; // << ok 
} 

perché la copia non richiede alcuna mutazione e non fornisce alcuna esposizione ai dati interni.

così finirete per dichiarare abbastanza spesso entrambe le varianti.

i risultati di dichiarare entrambi sono:

VectorHolder m; 
const VectorHolder c; 

m.getVector().size(); // << ok 
c.getVector().size(); // << ok - no mutation 

m.getVector().push_back(a); // << ok 
c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned 

quindi tutto risolve piacevolmente (a parte la ridondanza dei metodi).

2

La funzione getVector può essere dichiarata come const. Restituisce un riferimento che può essere modificato, quindi mentre la funzione effettiva non modifica nulla nella classe, il chiamante sarà in grado di modificare i dati interni.

dichiara come:

std::vector<int>& getVector(); 

Se si desidera una funzione per restituire un vettore che non può essere modificato, l'utilizzo del modificatore di const sia sul vettore e la funzione:

const std::vector<int>& getVector() const; 
0

Il motivo è che una funzione membro const dovrebbe restituire solo riferimenti const. Questo perché in una funzione const, ogni membro di dati diventa costante.

Pertanto è necessario dichiarare il getVector() in questo modo:

std::vector<int> &VectorHolder::getVector() const; 
+2

Indipendentemente da quanto sopra, probabilmente non è una buona idea esporre il contenitore interno. Se un giorno deciderai di migrare dal vettore a una mappa, i tuoi utenti ne risentiranno. Suggerirei invece di implementare gli iteratori. – Lev

Problemi correlati