Question

Je comprends que la fonction n'est pas autorisée à modifier l'état de l'objet, mais je pensais avoir lu quelque part que le compilateur était autorisé à supposer que si la fonction était appelée avec les mêmes arguments, elle renverrait la même valeur et ainsi pourrait réutiliser une valeur mise en cache si elle était disponible. par exemple

class object
{
    int get_value(int n) const
    {
        ...
    }

...


object x;

int a = x.get_value(1);
    ...
int b = x.get_value(1);

alors le compilateur pourrait optimiser le deuxième appel et utiliser la valeur dans un registre ou tout simplement faire b = a;

Est-ce vrai?

Était-ce utile?

La solution

const concerne la sémantique du programme et non les détails de la mise en oeuvre. Vous devez marquer une fonction membre const quand elle ne modifie pas l'état visible de l'objet et doit pouvoir être appelée sur un objet lui-même const . Dans une fonction membre const sur une classe X , le type de this est X const * : pointeur sur constante X objet. Ainsi, toutes les variables membres sont effectivement const dans cette fonction membre (sauf les mutables ). Si vous avez un objet const , vous ne pouvez appeler que des fonctions membres const .

Vous pouvez utiliser mutable pour indiquer qu'une variable membre peut changer même au sein d'une fonction membre const . Ceci est généralement utilisé pour identifier les variables utilisées pour la mise en cache des résultats, ou pour les variables n’affectant pas l’état observable réel, telles que les mutex (vous devez toujours verrouiller le mutex dans les fonctions membres const ) ou utiliser compteurs.

class X
{
    int data;
    mutable boost::mutex m;
public:
    void set_data(int i)
    {
        boost::lock_guard<boost::mutex> lk(m);
        data=i;
    }
    int get_data() const // we want to be able to get the data on a const object
    {
        boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
        return data;
    }
};

Si vous maintenez les données par pointeur plutôt que directement (y compris les pointeurs intelligents tels que std :: auto_ptr ou boost :: shared_ptr ), le pointeur devient . const dans une fonction membre const , mais pas les données pointées, vous pouvez donc modifier les données pointées.

En ce qui concerne la mise en cache: en général, le compilateur ne peut pas le faire car l'état peut changer entre les appels (en particulier dans mon exemple multi-threadé avec le mutex). Cependant, si la définition est en ligne, le compilateur peut extraire le code dans la fonction appelante et optimiser ce qu'il peut y voir. La fonction effectivement pourrait alors être appelée une seule fois.

La prochaine version de la C ++ Standard (C ++ 0x) aura un nouveau mot clé constexpr . Les fonctions marquées constexpr renvoient une valeur constante afin que les résultats puissent être mis en cache. Il y a des limites à ce que vous pouvez faire dans une telle fonction (afin que le compilateur puisse vérifier ce fait).

Autres conseils

Le mot clé mutable sur les variables membres permet aux fonctions const de modifier l’état de l’objet concerné.

Et non, il ne met pas en cache les données (du moins pas tous les appels) car le code suivant est une fonction const valide qui change avec le temps:

int something() const { return m_pSomeObject->NextValue(); }

Notez que le pointeur peut être const, bien que l'objet pointé ne soit pas const, donc l'appel de NextValue sur SomeObject peut ou non modifier son propre état interne. Cela provoque quelque chose dans la fonction qui retourne des valeurs différentes à chaque appel.

Cependant, je ne peux pas dire comment le compilateur fonctionne avec les méthodes const. J'ai entendu dire que certaines choses pouvaient être optimisées, mais il faudrait que je vérifie pour être certain.

Non.

Une méthode const est une méthode qui ne modifie pas l'état de l'objet (c'est-à-dire ses champs), mais vous ne pouvez pas supposer que, avec la même entrée, la valeur de retour d'une méthode const est déterminée. En d'autres termes, le mot clé const n'implique PAS que la fonction est un-à-un. Par exemple, une méthode qui renvoie l'heure actuelle est une méthode const, mais sa valeur de retour change entre les appels.

Le mot-clé const d'une fonction membre marque le paramètre this comme constant. La fonction peut toujours mettre en sourdine les données globales (ne peut donc pas être mise en cache), mais pas les données d'objet (permettant d'appeler des objets const).

Dans ce contexte, une fonction membre const signifie que this est également traité comme un pointeur const . Concrètement, cela signifie que vous n'êtes pas autorisé à modifier l'état de this dans une fonction membre const .

Pour les fonctions sans effet secondaire (c'est-à-dire ce que vous essayez d'atteindre), GCC dispose d'un "attribut de fonction". appelé pure (vous l'utilisez en disant __ attribut __ ((pur)) ): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

J'en doute, la fonction pourrait toujours appeler une fonction globale qui modifierait l'état du monde et ne violerait pas la const.

En plus du fait que la fonction membre peut modifier les données globales, il est possible pour la fonction membre de modifier explicitement les membres mutables déclarés de l'objet en question.

Corey a raison, mais n'oubliez pas que toutes les variables membres marquées comme mutables peuvent être modifiées dans les fonctions membres const.

Cela signifie également que ces fonctions peuvent être appelées à partir d'autres fonctions const ou via d'autres références const.

Edit: Bon sang, a été battu par 9 secondes .... 9 !!! :)

Les méthodes

const sont également autorisées à modifier les locales statiques. Par exemple, ce qui suit est parfaitement légal (et les appels répétés à bar () renverront des valeurs croissantes - et non un 0 mis en cache):

class Foo
{
public:
    int bar() const
    {
        static int x = 0;
        return x++;
    }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top