web-dev-qa-db-fra.com

vecteur const implique des éléments const?

const vector<A> Signifie-t-il que ses éléments sont également const?

Dans le code ci-dessous,

v[0].set (1234); dans void g ( const vector<A> & v ) produit l'erreur du compilateur

const.cpp: 28: 3: erreur: la fonction membre 'set' n'est pas viable: 'cet' argument a le type 'const value_type' (aka 'const A'), mais la fonction n'est pas marquée const

Pourquoi?

Mais (*v[0]).set(1234); Dans void h ( const vector<A *> & v ) est OK pour le compilateur.

Quelle est la différence entre les versions?

// ...........................................................
class A {
private:
  int a;
public:
  A (int a_) : a (a_) { }
  int get () const { return a; }
  void set (int a_) { a = a_; }
};

// ...........................................................
void g ( const vector<A> & v ) {
  cout << v[0].get();
  v[0].set (1234); 
} // ()

// ...........................................................
void h ( const vector<A *> & v ) {
  cout << (*v[0]).get();
  (*v[0]).set(1234);
} // ()
31
cibercitizen1

La première version

v[0].set (1234); 

ne compile pas car il essaie de changer le premier élément du vecteur qui lui est renvoyé par référence. Le compilateur pense que c'est un changement car set(int) n'est pas marqué const.

La deuxième version, d'autre part, seulement lit du vecteur

(*v[0]).set(1234);

et appelle set sur le résultat du déréférencement d'une référence constante à un pointeur qu'il récupère.

Lorsque vous appelez v[0] Sur un vecteur const, vous obtenez une référence const à A. Lorsque le type d'élément est un pointeur, appeler set dessus est OK. Vous pouvez remplacer le deuxième exemple par

v[0]->set(1234);

et obtenez le même résultat qu'auparavant. En effet, vous obtenez une référence à un pointeur qui est constant, mais l'élément pointé par ce pointeur n'est pas constant.

13
dasblinkenlight

Oui un const vector donne accès à ses éléments comme s'ils étaient const, c'est-à-dire qu'il ne vous donne que des références const. Dans votre deuxième fonction, ce ne sont pas les objets de type A qui sont const, mais pointeurs vers eux. Un pointeur étant const ne signifie pas que l'objet vers lequel le pointeur pointe est const. Pour déclarer un pointeur vers const, utilisez le type A const *.

20
lisyarus

Un objet const ne peut donc appeler que des méthodes const. C'est:

class V {
  public:
    void foo() { ... }        // Can't be called
    void bar() const  { ... } // Can be called
};

Regardons donc un opérateur du vecteur [] :

reference       operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;

Ainsi, lorsque l'objet vectoriel est const, il renvoie un const_reference.

À propos de: (*v[0]).set(1234);

Décomposons cela:

A * const & ptr = v[0];
A & val = *ptr;
val.set(1234);

Notez que vous disposez d'un pointeur constant vers des données variables. Vous ne pouvez donc pas modifier ce qui est pointé, mais vous pouvez modifier la valeur vers laquelle pointe le pointeur.

9
Bill Lynch