web-dev-qa-db-fra.com

Const_cast est-il sûr?

Je ne trouve pas beaucoup d'informations sur const_cast. La seule information que j'ai pu trouver (sur Stack Overflow) est:

La const_cast<>() est utilisée pour ajouter/supprimer la const (ness) (ou la volatilité-ness) d'une variable.

Cela me rend nerveux. L'utilisation d'un const_cast Peut-elle provoquer un comportement inattendu? Si oui, quoi?

Sinon, quand est-il acceptable d'utiliser const_cast?

87
Mag Roader

const_cast N'est sûr que si vous transtypez une variable qui était à l'origine non -const. Par exemple, si vous avez une fonction qui prend un paramètre d'un const char * Et que vous passez un char * Modifiable, il est prudent de const_cast Ce paramètre de revenir à un char * Et modifiez-le. Cependant, si la variable d'origine était en fait const, l'utilisation de const_cast Entraînera un comportement indéfini.

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR
85
Adam Rosenfield

Je peux penser à deux situations où const_cast est sûr et utile (il peut y avoir d'autres cas valides).

L'une est lorsque vous avez une instance const, une référence ou un pointeur et que vous souhaitez passer un pointeur ou une référence à une API qui n'est pas const-correcte, mais que vous êtes CERTAIN ne modifierez pas l'objet. Vous pouvez const_caster le pointeur et le transmettre à l'API, en vous assurant qu'il ne changera vraiment rien. Par exemple:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

L'autre est si vous utilisez un ancien compilateur qui n'implémente pas "mutable" et que vous souhaitez créer une classe qui est logiquement const mais pas const au niveau du bit. Vous pouvez const_cast 'this' dans une méthode const et modifier les membres de votre classe.

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};
34
Fred Larson

J'ai du mal à croire que ce sont les seules informations que vous pouvez trouver sur const_cast. Citant de la deuxième hit Google :

Si vous supprimez la constance d'un objet qui a été explicitement déclaré comme const et essayez de le modifier, les résultats ne sont pas définis.

Cependant, si vous supprimez la constance d'un objet qui n'a pas été explicitement déclaré comme const, vous pouvez le modifier en toute sécurité.

22
Rob Kennedy

Ce qu'Adam dit. Un autre exemple où const_cast peut être utile:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

Nous ajoutons d'abord const au type this pointe vers, puis nous appelons la version const de getT, puis nous supprimons const du type de retour, qui est valide puisque t doit être non-const (sinon, la version non-const de getT n'aurait pas pu être appelée). Cela peut être très utile si vous avez un grand corps de fonction et que vous souhaitez éviter le code redondant.

10

La réponse courte est non, ce n'est pas sûr.

La réponse longue est que si vous en savez assez pour l'utiliser, cela devrait être sûr.

Lorsque vous lancez un casting, ce que vous dites essentiellement est: "Je sais quelque chose que le compilateur ne sait pas." Dans le cas de const_cast, ce que vous dites est: "Même si cette méthode prend une référence ou un pointeur non const, je sais qu'elle ne changera pas le paramètre que je lui transmets."

Donc, si vous savez réellement ce que vous prétendez savoir en utilisant le casting, alors c'est bien de l'utiliser.

9
JohnMcG

Vous détruisez toute chance de sécurité des threads, si vous commencez à modifier des choses que le compilateur pensait const.

5
Matt Cruikshank