En tant que programmeur C++ débutant, il y a quelques constructions qui me semblent encore très obscures, l'une d'entre elles est const
. Vous pouvez l'utiliser dans de nombreux endroits et avec autant d'effets différents qu'il est presque impossible pour un débutant de sortir vivant. Est-ce qu'un gourou C++ expliquera une fois pour toutes les différentes utilisations et si et/ou pourquoi ne pas les utiliser?Combien et quelles sont les utilisations de "const" en C++?
Répondre
Essayer de recueillir des utilisations:
Binding certains temporaires pour faire référence à const, pour allonger sa durée de vie. La référence peut être une base - et la destructor de celui-ci n'a pas besoin d'être virtuel - le droit destructor est encore appelé:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
Explication, en utilisant le code:
struct ScopeGuard {
~ScopeGuard() { } // not virtual
};
template<typename T> struct Derived : ScopeGuard {
T t;
Derived(T t):t(t) { }
~Derived() {
t(); // call function
}
};
template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }
Cette trick est utilisé dans la classe d'utilité ScopeGuard d'Alexandrescu. Une fois que le temporaire est hors de portée, le destructeur de Derived est appelé correctement. Le code ci-dessus manque quelques petits détails, mais c'est le gros problème.
Utilisez const pour dire aux autres méthodes ne changera pas l'état logique de cet objet.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
Utilisez const pour la copie-sur-écriture des classes, pour faire l'aide du compilateur vous de décider quand et quand ne vous devez copier.
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
Explication: Vous pouvez partager des données lorsque vous copiez quelque chose d'aussi longtemps que les données de l'origine et l'objet copie'd restent les mêmes. Une fois que l'un des objets change de données, vous avez besoin de deux versions: une pour l'original et une pour la copie. Autrement dit, vous copier sur un écrire à l'un ou l'autre objet, de sorte qu'ils ont maintenant tous les deux leur propre version.
En utilisant le code:
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
L'imprimante extrait ci-dessus la même adresse sur mon GCC, car la bibliothèque C++ utilisé implémente une copie sur écriture std::string
. Les deux chaînes, même si elles sont des objets distincts, partagent la même mémoire pour leurs données de chaîne. Faire b
non-const préférera la version non-const du operator[]
et GCC va créer une copie de la mémoire tampon de sauvegarde, car nous pourrions le changer et il ne doit pas affecter les données de a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Pour la copie-constructeur de faire des copies à partir d'objets const et Temporaries:
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Pour faire des constantes qui trivialement ne peut pas changer
double const PI = 3.1415;
Pour passer des objets arbitraires par référence au lieu de la valeur par - pour éviter peut-être coûteux, voire impossible, par valeur passant
void PrintIt(Object const& obj) {
// ...
}
Pouvez-vous expliquer s'il vous plaît la première et la troisième utilisation dans vos exemples? – tunnuz
"Pour garantir à l'appelé que le paramètre ne peut pas être NULL", je ne vois pas comment const a quelque chose à voir avec cet exemple. –
oups, j'échoue tellement. J'ai commencé à écrire des références. je vous remercie beaucoup pour gémir :) je vais bien sûr supprimer ce genre de choses maintenant :) –
Il y a vraiment deux utilisations principales de const en C++.
Const valeurs
Si une valeur est sous la forme d'une variable, membre ou d'un paramètre qui ne (ou ne devrait pas) être modifiée au cours de sa durée de vie, vous devriez marquer const. Cela aide à prévenir les mutations sur l'objet. Par exemple, dans la fonction suivante, je n'ai pas besoin de changer l'instance de Student passée donc je la marque const.
void PrintStudent(const Student& student) {
cout << student.GetName();
}
En ce qui concerne pourquoi vous le feriez. Il est beaucoup plus facile de raisonner sur un algorithme si vous savez que les données sous-jacentes ne peuvent pas changer. "const" aide, mais ne garantit pas que cela sera réalisé.
De toute évidence, les données d'impression à Cout ne nécessite pas beaucoup de pensée :)
Marquage d'une méthode membre const
Dans l'exemple précédent, je marqué des étudiants const. Mais comment C++ savait-il que l'appel de la méthode GetName() à l'étudiant ne ferait pas muter l'objet? La réponse est que la méthode a été marquée comme const. Marquer une méthode "const" fait 2 choses. Principalement il indique à C++ que cette méthode ne mutera pas mon objet. La deuxième chose est que toutes les variables membres seront maintenant traitées comme si elles étaient marquées comme const. Cela vous aide mais ne vous empêche pas de modifier l'instance de votre classe.
Ceci est un exemple extrêmement simple mais j'espère que cela aidera à répondre à vos questions.
Prenez soin de comprendre la différence entre ces 4 déclarations:
Les 2 déclarations suivantes sont identiques sémantiquement. Vous pouvez changer où point ccp1 et ccp2, mais vous ne pouvez pas changer la chose qu'ils pointent. Ensuite, le pointeur est const, donc pour être significatif, il doit être initialisé pour pointer vers quelque chose.
const char* ccp1;
char const* ccp2;
Vous ne pouvez pas le faire pointer vers quelque chose d'autre, mais la chose qu'il indique
peut être changé.
char* const cpc = &something_possibly_not_const;
Enfin, nous combinons les deux - si la chose étant pointé du doigt ne peut pas être modifié, et le pointeur ne peut pas pointer vers nulle part ailleurs.
const char* const ccpc = &const_obj;
La règle en spirale dans le sens horaire peut aider à dénouer une déclaration http://c-faq.com/decl/spiral.anderson.html
D'une manière détournée, oui c'est le cas! La règle en spirale dans le sens des aiguilles d'une montre le décrit mieux: commencez par le nom (kpPointer) et tracez une spirale dans le sens des aiguilles d'une montre à travers le jeton, et dites chaque jeton. Evidemment, il n'y a rien à droite de kpPointer mais ça marche toujours. –
Comme une petite note, comme je l'ai lu here, il est utile de noter que
const
applique à tout ce qui est sur son immédiate à gauche (sauf si il n'y a rien, auquel cas il s'applique à tout ce qui est immédiatement à droite).
- 1. Quelles sont les utilisations légitimes des crochets de clavier globaux?
- 2. Quelles sont les utilisations des paramètres de modèle de modèle en C++?
- 3. Quelles sont les utilisations intéressantes pour les agents Java?
- 4. Quelles sont les utilisations des métadonnées de Clojure?
- 5. Quelles sont les utilisations pratiques du fichier resx?
- 6. Quelles sont vos utilisations les plus courantes pour les expressions régulières?
- 7. Quelles sont les conventions pour les en-têtes et les fichiers cpp en C++?
- 8. const Dictionnaire en C#
- 9. Quelles sont les longueurs des types de données communs?
- 10. Quelles sont les variables initialisées en Delphi?
- 11. Combien de bogues sont possibles?
- 12. Quelles sont les utilisations les plus pratiques que vous avez appliquées à la méthode data() de jQuery?
- 13. Où sont les utilisations intelligentes de l'évaluation stricte?
- 14. Quelles sont les modifications empilables?
- 15. Quelles sont les différences entre les délégués et les événements?
- 16. Quelles sont les façons de résoudre les fuites de mémoire en C#
- 17. Quelles sont les capacités de Moq et Rhino.mocks?
- 18. C question de const
- 19. Comment importer const int * const buffer [] en C#?
- 20. Projet large "Supprimer et trier les utilisations"
- 21. Quelles sont les conventions de dénomination les plus courantes en C#?
- 22. Quelles sont les différences de rendu entre FF2 et FF3?
- 23. Quelles sont les dimensions de l'écran iPhones pour le codage?
- 24. MSBuild, solution VS2008 et CI - quelles sont les meilleures pratiques?
- 25. erreur C avec pointeur et const char []
- 26. utilisations de « pour » en Java
- 27. Quelles sont les meilleures ressources pour apprendre l'écriture idiomatique C#?
- 28. Objectif-C Quelles sont les choses entre parenthèses?
- 29. Quelles sont les commandes importantes de Ruby?
- 30. Quelles sont les fonctionnalités cachées de Maven2?
exactement à la recherche de cette question: D – alamin