Disons que j'ai une classe qui ressemble à ceci (ce n'est qu'un exemple):
class A {
double *ptr;
public:
A() : ptr( new double[100] ) {}
A( const A &other ) {
other.ptr[7] = 15;
}
void doNotChangeMyData() const {
ptr[43] = 14;
}
void changeMyData() {
ptr[43] = 14;
}
~A() { delete[] ptr; }
};
Le const
constructeur de copie et la doNotChangeMyData
fonction le rendent ptr
impossible à modifier; cependant, cela me permet toujours de modifier le contenu du tableau pointé par ptr
.
Existe-t-il un moyen d'empêcher le contenu du ptr
tableau de d'être modifié dans les const
instances uniquement, à moins de "faire attention" (ou de s'éloigner du pointeur brut)?
Je sais que je pourrais faire quelque chose comme
void doNotChangeMyData() const {
const double *const ptr = this->ptr;
ptr[43] = 14; // then this would fail to compile
}
Mais je préfère ne pas avoir à ...
std::vector
std::vector::operator[]()
peut modifier les valeurs à droite?vector
marcherait.std::vector::operator[]() const
renvoie uneconst
référenceRéponses:
Les pointeurs ne se propagent pas
const
. L'ajoutconst
au typedouble*
donnedouble* const
, ce qui entraîne une non-const
valeur lorsqu'il est déréférencé.Au lieu de cela, vous pouvez utiliser
std::vector
:a
std::array
:ou un tableau intégré (non recommandé):
Les trois options se propagent
const
.Si vous voulez vraiment utiliser des pointeurs (fortement déconseillés), utilisez au moins un
std::unique_ptr
pour éviter la gestion manuelle de la mémoire. Vous pouvez utiliser l'std::experimental::propagate_const
encapsuleur des principes fondamentaux de la bibliothèque 2 TS:Ce n'est pas encore dans la norme, mais de nombreux compilateurs le prennent en charge. Bien sûr, cette approche est inférieure aux conteneurs appropriés.
la source
std::array
ne fonctionne pas, si vous ne connaissez pas la taille au moment de la compilation.vector
ajoute des frais généraux;unique_ptr
n'ajoute pas de surcharge mais si le pointeur doit être partagé, alors vous avez besoin de celuishared_ptr
qui ajoute la surcharge. Je ne pense pas que VS supporte actuellementpropagate_const
(au moins le fichier d'en-tête référencé par cppreference n'existe pas avec/std:c++latest
) :(vector
TBH est souvent surestimée, en particulier par rapport à l'effort de gestion manuelle de la mémoire. De plus, si vous partagez les pointeurs manuellement, vous devez utiliser un décompte de références, de sorte que la surcharge n'est pas particulière àshared_ptr
. Je ne savais pas que VS ne supporte paspropagate_const
encore (GCC et Clang le supportent tous les deux IIRC), mais il n'est pas difficile de déployer le nôtre selon les spécifications.vector
puis prend son contenu via.data()
ou&vec[0]
et travaille directement avec cela à la place. Dans le cas du partage, j'ai souvent un propriétaire du pointeur qui crée et supprime, mais d'autres classes partagent les données.