it-swarm.com.de

Ist const_cast sicher?

Ich kann nicht viele Informationen zu const_cast Finden. Die einzigen Informationen, die ich (bei Stack Overflow) finden konnte, sind:

Die Funktion const_cast<>() dient zum Hinzufügen/Entfernen der Konstante (oder der Flüchtigkeit) einer Variablen.

Das macht mich nervös. Kann die Verwendung von const_cast Zu unerwartetem Verhalten führen? Wenn ja, was?

Wann kann alternativ const_cast Verwendet werden?

87
Mag Roader

const_cast ist nur dann sicher, wenn Sie eine Variable umwandeln, die ursprünglich nicht -const war. Wenn Sie beispielsweise eine Funktion haben, die den Parameter const char *, und Sie übergeben ein änderbares char *, es ist sicher zu const_cast dieser Parameter zurück zu einem char * und ändern Sie es. Wenn die ursprüngliche Variable jedoch tatsächlich const war, verwenden Sie const_cast führt zu undefiniertem Verhalten.

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

Ich kann mir zwei Situationen vorstellen, in denen const_cast sicher und nützlich ist (es kann auch andere gültige Fälle geben).

Eine davon ist, wenn Sie über eine konstante Instanz, einen konstanten Verweis oder einen konstanten Zeiger verfügen und einen Zeiger oder einen Verweis auf eine API übergeben möchten, die nicht konstant ist, bei der Sie jedoch BESTIMMT sind, dass das Objekt nicht geändert wird. Sie können den Zeiger const_cast und an die API übergeben, in der Gewissheit, dass er nichts wirklich ändert. Beispielsweise:

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()));
}

Die andere Möglichkeit ist, wenn Sie einen älteren Compiler verwenden, der "mutable" nicht implementiert, und eine Klasse erstellen möchten, die logisch const, aber nicht bitweise const ist. Sie können const_cast 'this' innerhalb einer const-Methode und Member Ihrer Klasse ändern.

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

Es fällt mir schwer zu glauben, dass dies die einzigen Informationen sind, die Sie über const_cast finden können. Zitat aus dem zweiter Google-Hit :

Wenn Sie die Konstanz eines Objekts, das explizit als const deklariert wurde, verwerfen und versuchen, sie zu ändern, sind die Ergebnisse undefiniert.

Wenn Sie jedoch die Konstanz eines Objekts verwerfen, das nicht explizit als const deklariert wurde, können Sie sie sicher ändern.

22
Rob Kennedy

Was Adam sagt. Ein weiteres Beispiel, in dem const_cast hilfreich sein kann:

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;
};

Wir fügen zuerst const zum Typ hinzu, auf den this verweist, rufen dann die const-Version von getT auf und entfernen dann const aus dem Rückgabetyp, der seit t gültig ist. muss nicht const sein (andernfalls hätte die nicht const Version von getT nicht aufgerufen werden können). Dies kann sehr nützlich sein, wenn Sie einen großen Funktionskörper haben und redundanten Code vermeiden möchten.

Die kurze Antwort ist nein, es ist nicht sicher.

Die lange Antwort lautet: Wenn Sie genug wissen, um es zu verwenden, sollte es sicher sein.

Beim Casting sagen Sie im Wesentlichen: "Ich weiß etwas, was der Compiler nicht weiß." Im Fall von const_cast sagen Sie: "Auch wenn diese Methode eine Nicht-const-Referenz oder einen Zeiger verwendet, weiß ich, dass der Parameter, den ich übergebe, nicht geändert wird."

Wenn Sie also tatsächlich wissen, was Sie angeblich über die Verwendung des Casts wissen, ist es in Ordnung, es zu verwenden.

9
JohnMcG

Sie zerstören jede Chance auf Thread-Sicherheit, wenn Sie Dinge ändern, die der Compiler für const hielt.

5
Matt Cruikshank