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);
} // ()
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.
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 *
.
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
.
(*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.