web-dev-qa-db-fra.com

Renvoie une référence à une variable membre vectorielle

J'ai un vecteur en tant que membre d'une classe et je souhaite lui renvoyer une référence via une fonction getVector (), afin de pouvoir le modifier ultérieurement. Ne vaut-il pas mieux utiliser la fonction getVector () pour être const? Cependant, j'ai eu une erreur "qualificatifs abandonnés dans une référence de liaison de type ..." dans le code suivant. Qu'est-ce qui devrait être modifié? 

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;
}
26
arjacsoh

S'agissant d'une fonction membre const, le type de retour ne peut pas être une référence non const. Faites-le const:

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

Maintenant ça va. 

Pourquoi ça va? Parce que dans une fonction membre const, chaque membre devient const de telle sorte qu'il ne puisse pas être modifié, ce qui signifie que myVector est un vecteur const dans la fonction, c'est pourquoi vous devez également définir le type de retour const , s'il retourne le reference.

Maintenant, vous ne pouvez pas modifier l'objet même. Voyez ce que vous pouvez faire et ce qui ne peut pas:

 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

En passant, je me demande pourquoi vous avez besoin d'une telle variable VectorHolder en premier lieu.

30
Nawaz

il n'est pas rare de déclarer les variantes const et mutable, comme ceci:

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

le problème sous-jacent à votre programme est que vous renvoyez une référence non-const à partir d'une méthode const.

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

donc vous le faites en utilisant ce formulaire:

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

et lorsqu'il s'agit d'une méthode non const ou que le client détient une référence non const, vous pouvez utiliser légalement une méthode non const:

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

enfin, vous pouvez retourner une valeur (dans certains cas):

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

parce que la copie ne nécessite aucune mutation et ne fournit aucune exposition aux données internes.

vous finirez donc par déclarer les deux variantes assez souvent.

les résultats de déclarer les deux sont:

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

donc tout fonctionne bien (mis à part la redondance des méthodes).

13
justin

La fonction getVector peut être déclarée en tant que const. Il renvoie une référence qui peut être modifiée. Ainsi, si la fonction réelle ne modifie rien dans la classe, l'appelant pourra modifier les données internes.

Déclarez-le comme:

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

Si vous voulez qu'une fonction retourne un vecteur qui ne peut pas être modifié, utilisez le modificateur const sur le vecteur et la fonction:

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

La raison en est qu'une fonction membre const doit uniquement renvoyer des références const. En effet, dans une fonction const, chaque membre de données devient constant.

Par conséquent, vous devez déclarer le getVector () de cette façon:

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