web-dev-qa-db-fra.com

fonction membre c ++ const qui retourne un pointeur const .. Mais quel type de const est le pointeur renvoyé?

Je m'excuse si cela a été demandé, mais comment puis-je créer une fonction membre en c ++ qui renvoie un pointeur dans les scénarios suivants: 1. Le pointeur renvoyé est constant, mais le fichier indésirable peut être modifié. 2. Le courrier indésirable à l'intérieur est constant, mais le pointeur renvoyé peut être modifié. 3. Ni le courrier indésirable, ni le pointeur ne peuvent être modifiés.

Est-ce comme ça:

  1. int *const func() const
  2. const int* func() const
  3. const int * const func() const

Tous les tutoriels que j'ai lus ne couvrent pas cette distinction.

Note latérale: Si ma méthode est déclarée const, les didacticiels disent que je déclare que je ne modifierai pas les paramètres. Mais ce n'est pas assez clair pour moi dans le cas où un paramètre est un pointeur. Mes paramètres doivent-ils ressembler à:

une. void func(const int* const x) const;
b. void func(const int* x) const;
c. void func(const int* const x) const;

33
Jor

Certaines utilisations de const n'ont pas vraiment de sens.

Supposons que vous ayez la fonction suivante:

void myFunction (const int value);

Le const indique au compilateur que la valeur ne doit pas changer dans la fonction. Cette information n'a aucune valeur pour l'appelant. C'est à la fonction elle-même de décider quoi faire avec la valeur. Pour l'appelant, les deux définitions de fonction suivantes se comportent exactement de la même manière pour lui:

void myFunction (const int value);
void myFunction (int value);

Parce que valeur est passée par valeur, ce qui signifie que la fonction obtient quand même une copie locale.

D'autre part, si l'argument est une référence ou un pointeur, les choses deviennent très différentes.

void myFunction (const MyClass &value);

Cela indique à l'appelant que la valeur est transmise par référence (ainsi, derrière les écrans, il s'agit en fait d'un pointeur), mais l'appelant promet de ne pas modifier la valeur . Il en va de même pour les pointeurs:

void myFunction (const MyClass *value);

Nous passons un pointeur sur MyClass (pour des raisons de performances), mais la fonction promet de ne pas changer la valeur.

Si nous écrivions ce qui suit:

void myFunction (MyClass * const value);

Ensuite, nous sommes de retour dans la première situation. myFunction obtient un pointeur, qui est passé par valeur et qui est const. Étant donné que MyFunction obtient une copie de la valeur du pointeur, le fait que l'appelant soit const ou pas importe peu. La chose la plus importante est que myFunction puisse modifier le contenu de la valeur, car la variable de pointeur elle-même est const, mais que le contenu de celle-ci ne l’est pas.

La même chose est vraie pour les valeurs de retour:

const double squareRoot(double d);

Cela n'a aucun sens. squareRoot renvoie un double const, mais comme il est passé 'par valeur' ​​et qu'il doit donc être copié dans ma propre variable locale, je peux en faire ce que je veux.

D'autre part:

const Customer *getCustomer(char *name);

Me dit que getCustomer me renvoie un pointeur à un client et que je ne suis pas autorisé à en modifier le contenu.

En fait, il vaudrait mieux que le paramètre char-pointer-content soit aussi constant, car je ne m'attends pas à ce que la fonction modifie la chaîne donnée:

const Customer *getCustomer(const char *name);
13
Patrick

Renvoyer un pointeur sur const a beaucoup de sens, mais retourner un pointeur const (vous ne pouvez pas le modifier) ​​n'ajoute généralement aucune valeur (bien que certains disent qu'il peut empêcher les erreurs des utilisateurs ou ajouter une optimisation du compilateur).

C’est parce que la valeur de retour appartient à l’appelant de la fonction, c’est-à-dire qu’il s’agit de sa propre copie; il n’est donc pas important qu’ils le modifient (pour indiquer autre chose). Le contenu n'appartient toutefois pas à l'appelant et l'implémenteur de la fonction peut conclure un contrat en tant qu'information en lecture seule.

Les fonctions membres de Const promettent de ne pas changer l'état de la classe, bien que cela ne soit pas forcément appliqué en réalité par le compilateur. Je ne fais pas ici référence à const_cast ou aux membres mutables, mais au fait que si votre classe contient des pointeurs ou des références, une fonction membre const transforme vos pointeurs en pointeurs constants sans les transformer en pointeurs, même vos références ne sont pas transformées. en références-à-const. S'il s'agit de composants de votre classe (et que ces composants sont souvent représentés par des pointeurs), vos fonctions peuvent changer leur état.

Les membres mutables sont là pour permettre à votre classe de les changer sans changer d'état interne. Ceux-ci peuvent généralement être appliqués à:

  • Les mutex que vous souhaitez verrouiller même pour la lecture.
  • Les données chargées paresseux, c’est-à-dire qu’elles sont renseignées lors du premier accès.
  • Objets comptés en référence: vous voulez augmenter le nombre de références s'il a un autre visualiseur, vous modifiez donc son état juste pour le lire.

const_cast est généralement considéré comme un "hack" et est souvent utilisé lorsque quelqu'un d'autre n'a pas écrit son code correctement avec const-correct. Il peut avoir de la valeur dans les situations suivantes:

  • Plusieurs surcharges où l'une est const et une non-const et le const renvoie une référence const et le non-const renvoie une référence non-const, mais sinon, elles sont identiques. Dupliquer le code (si ce n'est pas un simple membre de données) n'est pas une bonne idée, alors implémentez-le l'un par rapport à l'autre et utilisez const_cast pour contourner le compilateur.

  • Où vous voulez en particulier appeler la surcharge const mais avoir une référence non const. Jetez-le en premier.

1
CashCow

La méthode const vous empêche de modifier les membres. Dans le cas de pointeurs, cela signifie que vous ne pouvez pas réaffecter le pointeur. Vous pouvez modifier l'objet pointé par le pointeur vers le désir de votre coeur.

Comme le pointeur est renvoyé par valeur (une copie), l'appelant ne peut pas l'utiliser pour modifier le membre pointeur de la classe. Par conséquent, ajouter const à la valeur de retour n’ajoute rien.

Les choses sont différentes si vous deviez renvoyer une référence au pointeur. Si le pointeur n'était pas const, cela voudrait dire qu'une fonction qui n'a pas le droit de modifier une valeur accorde ce droit à l'appelant.

Exemple:

class X
{
    int* p;
public:
    int* get_copy_of_pointer() const //the returned value is a copy of this->p
    { 
        *p = 42;  //this being const doesn't mean that you can't modify the pointee
        //p = 0;  //it means you can't modify the pointer's value
        return p; 
    }
    int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer
    {
        return p;
    }
};
0
visitor