Question

Je sais qu'il ya quelques questions au sujet de la correction const où il est indiqué que la déclaration d'une fonction et sa définition ne doivent pas nécessairement d'accord pour les paramètres de valeur. En effet, le constness d'un paramètre de valeur compte que dans la fonction. Ceci est bien:

// header
int func(int i);

// cpp
int func(const int i) {
    return i;
}

fait ce vraiment une bonne pratique? Parce que je ne l'ai jamais vu quelqu'un le faire. Je l'ai vu cette citation (pas sûr de la source) dans d'autres endroits cela a été discuté:

  

« En fait, au compilateur, la signature de la fonction est la même si vous incluez cette const en face d'un paramètre de valeur ou non. »

     

« Évitez les paramètres passe par valeur const dans les déclarations de fonction. Toujours faire le paramètre const dans la définition de la même fonction si elle ne sera pas modifié. »

Le deuxième paragraphe dit de ne pas mettre la const dans la déclaration. Je suppose que cela est parce que le constness d'un paramètre de valeur n'a pas de sens dans le cadre d'une définition d'interface. Il est un détail de mise en œuvre.

Sur la base de cette recommandation, est-il également recommandé pour les valeurs de pointeur de paramètres de pointeur? (Il n'a pas de sens sur un paramètre de référence puisque vous ne pouvez pas réassigner une référence.)

// header
int func1(int* i);
int func2(int* i);

// cpp
int func1(int* i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compiles without error

    return *i;
}
int func2(int* const i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compile error

    return *i;
}

Résumé: Faire des paramètres de valeur est utile pour attraper des erreurs logiques. Est-il une meilleure pratique? Pensez-vous aller à l'extrême de quitter la const sur le fichier d'en-tête? Est-il aussi utile aux valeurs de pointeur const? Pourquoi ou pourquoi pas?

Quelques références:

C ++ mot-clé const - utiliser généreusement Utilisation de 'const' pour les paramètres de fonction

Un exemple lorsque les paramètres de valeur const sont utiles:

bool are_ints_equal(const int i, const int j) {
    if (i = j) { // without the consts this would compile without error
        return true;
    } else {
        return false;
    }
    // return i = j; // I know it can be shortened
}
Était-ce utile?

La solution

Mon avis sur la question:

Il est pas une mauvaise idée, mais la question est mineure et votre énergie pourrait être mieux dépensé sur d'autres choses.

Dans votre question vous avez fourni un bon exemple de quand il pourrait attraper une erreur, mais parfois vous finissez par faire aussi quelque chose comme ceci:

void foo(const int count ...)
{
   int temp = count;  // can't modify count, so we need a copy of it
   ++temp;

   /* ... */
}

Les avantages et les inconvénients sont mineures dans les deux cas.

Autres conseils

Je l'ai lu plusieurs fois que les paramètres de prise de valeur dans une fonction const est une mauvaise chose à faire, car il est inutile.

Cependant, je trouve de temps en temps utile pour moi comme un chèque que ma mise en œuvre ne fait pas quelque chose que je ne veux pas (comme dans l'exemple à la fin de votre question).

Ainsi, alors qu'il ne peut pas ajouter de la valeur à l'appelant, il n'ajoute un petit peu de valeur pour moi parfois comme réalisateur, et il ne lui enlève rien de l'appelant. Donc, je ne vois pas de mal à l'utiliser.

Par exemple, j'implantera une fonction C qui prend des pointeurs de couple pour un tampon - un pointeur vers le début, et un pointeur vers la fin. Je vais mettre les données dans la mémoire tampon, mais que vous voulez faire en sorte que je n'envahit pas la fin. Donc, dans la fonction, il est le code qui incrémente un pointeur que j'ajoute des données. Faire le pointeur vers la fin du tampon un paramètre de const veillera à ce que je ne code pas un bug qui incrémente accidentellement le pointeur de la limite de fin au lieu du pointeur que je devrais vraiment être incrémentée.

fonction FillArray avec une signature comme ceci:

size_t fillArray( data_t* pStart, data_t* const pEnd);

me empêcher de incrémenter accidentellement pEnd quand je veux vraiment augmenter pStart. Ce n'est pas une chose énorme, mais je suis sûr tout le monde qui a programmé pour une période de temps en C a couru à travers un tel bug.

Malheureusement, certains compilateurs (je vous regarde, Sun CC!) Se différencient de manière incorrecte entre les arguments déclarés const et les non déclarés ainsi, et vous pouvez obtenir des erreurs sur les fonctions non définies.

Je pense que cela dépend de votre style personnel.

Il n'ajoute pas ou soustraire à ce que les clients peuvent passer à votre fonction. En substance, il est comme une affirmation de la compilation. Si cela vous aide à savoir que la valeur ne changera pas, allez-y et de le faire, mais je ne vois pas une grande raison pour les autres de le faire.

L'une des raisons que je ne pourrais pas le faire est que la const-ness du paramètre de valeur est un détail de mise en œuvre que vos clients ne ont pas besoin de connaître. Si plus tard (volontairement) changer votre fonction afin qu'il ne fait changer cette valeur, vous devez changer la signature de votre fonction, ce qui forcera vos clients à recompiler.

Ceci est similaire à la raison pour laquelle certaines personnes recommandent ne pas avoir des méthodes virtuelles publiques (les fonctions ness virtuel est un détail de mise en œuvre qui doit être caché des clients), mais je ne suis pas dans ce camp particulier.

S'il est présent mot-clé const; cela signifie que la valeur de « i » (qui est de type const) ne peut pas être modifié. Si la valeur de « i » est changé à l'intérieur compilateur fonction foo jetteront erreur: «

  

Impossible de modifier un objet const

Mais le changement '* i' (à savoir * i = 3;) signifie que vous ne changez pas la valeur de 'i', mais la valeur de l'adresse pointée par 'i'

En fait, la fonction const est approprié pour de grands objets qui ne doivent pas être modifiées par la fonction.

Nous avons tous à dénouer quelqu'un d'autre code C ++ de temps en temps. Et que quelqu'un d'autre code de C ++ est un désordre complet par définition. D

Alors la 1ère chose que je fais toujours de déchiffrer (flux de données local et global) est mis const dans chaque définition de la variable jusqu'à ce que le compilateur se plaint. Cela signifie également des arguments de valeur const-qualification, et il aide vraiment éviter les variables qui ont été modifiées au milieu de la fonction sans me le remarquer ...

Je comprends donc vraiment quand que quelqu'un d'autre const partout (y compris les paramètres de valeur): D

J'aime correcte de const pour des situations comme celle-ci:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

Cela me permet d'utiliser b sans crainte de le modifier, mais je ne dois pas payer le coût d'un constructeur de copie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top