Domanda

Non riesco a trovare molte informazioni su const_cast. L'unica informazione che ho trovato (su Stack Overflow) è:

  

Il const_cast<>() viene utilizzata per aggiungere / rimuovere const (Ness) (o volatili-Ness) di una variabile.

Questo mi rende nervoso. Potrebbe utilizzare un <=> causare un comportamento imprevisto? Se sì, quali?

In alternativa, quando è bene utilizzare <=>?

È stato utile?

Soluzione

const_cast è sicura solo se si sta gettando una variabile che non era in origine - const. Ad esempio, se si dispone di una funzione che prende un parametro di un const char *, e si passa in un modificabile char *, è sicuro di <=> quel parametro di nuovo ad un <=> e modificarlo. Tuttavia, se la variabile originale era infatti <=>, quindi utilizzando <=> si tradurrà in un comportamento indefinito.

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

Altri suggerimenti

Mi vengono in mente due situazioni in cui const_cast è sicuro e utile (ci possono essere altri casi validi).

Una è quando si ha un const esempio, di riferimento, o un puntatore, e si desidera passare un puntatore o il riferimento a un'API che non è const-correct, ma che sei certo non modificare l'oggetto. È possibile const_cast il puntatore e passarlo al API, confidando che non cambierà davvero nulla. Ad esempio:

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'altro è se si sta utilizzando un compilatore più vecchio che non implementa 'mutevoli', e si desidera creare una classe che è logicamente const ma non const bit a bit. È possibile const_cast 'questo' all'interno di un metodo const e modificare i membri della tua 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];
    }
};

Lo trovo difficile credere che questo è il solo informazioni si potrebbe trovare su const_cast. Citando dal secondo Google ha colpito :

  

Se lanci via la costanza di un   oggetto che è stato esplicitamente   dichiarata come const, e il tentativo di   modificarlo, i risultati sono indefiniti.

     

Tuttavia, se lanci via il   costanza di un oggetto che non ha   stato esplicitamente dichiarato come const, si   può modificare in modo sicuro.

Cosa dice Adam. Un altro esempio in cui const_cast può essere 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;
};

Per prima cosa aggiungiamo const al tipo this punti, allora chiamiamo la versione const di getT, e poi togliamo const dal tipo di ritorno, che è valida in quanto t devono essere non-const ( in caso contrario, la versione non-const di <=> non avrebbe potuto essere chiamato). Questo può essere molto utile se si ha un grande corpo funzione e si vuole evitare di codice ridondante.

La risposta breve è no, non è sicura.

La risposta lunga è che se si conosce abbastanza per usarlo, allora dovrebbe essere al sicuro.

Quando si sta gettando, ciò che si sta essenzialmente dicendo è: "So qualcosa che il compilatore non lo sa." Nel caso di const_cast, quello che stai dicendo è: "Anche se questo metodo richiede un riferimento o un puntatore non-const, so che non cambierà il parametro lo passo".

Quindi, se non sa cosa si richieda di conoscere in utilizzando il cast, allora va bene usarlo.

Si sta distruggendo ogni possibilità di thread-sicurezza, se si avvia modificano le cose che il compilatore pensavamo fossero const.

#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}

fonte: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_const_cast.htm

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top