O const_cast é seguro?

Não consigo encontrar muita informação sobre const_cast . A única informação que pude encontrar (no Stack Overflow) é:

O const_cast() é usado para adicionar / remover const (ness) (ou volatilidade) de uma variável.

Isso me deixa nervoso. Poderia usar um const_cast causar comportamento inesperado? Se sim, o que?

Alternativamente, quando é const_cast usar o const_cast ?

const_cast é seguro apenas se você estiver lançando uma variável que originalmente não era const . Por exemplo, se você tem uma function que pega um parâmetro de const char * , e você passa um char * modificável char * , é seguro fazer const_cast desse parâmetro de volta para um char * e modificá-lo. No entanto, se a variável original foi, de fato, const , então usar const_cast resultará em um comportamento indefinido.

 void func(const char *param, size_t sz, bool modify) { if(modify) strncpy(const_cast(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 

Eu posso pensar em duas situações em que const_cast é seguro e útil (pode haver outros casos válidos).

Uma é quando você tem uma instância const, uma referência ou um ponteiro, e deseja passar um ponteiro ou referência a uma API que não seja const-correta, mas que você está CERTAIN não modificará o object. Você pode const_cast o ponteiro e passá-lo para a API, confiando que ele realmente não vai mudar nada. Por exemplo:

 void log(char* text); // Won't change text -- just const-incorrect void my_func(const std::string& message) { log(const_cast(&message.c_str())); } 

A outra é se você estiver usando um compilador antigo que não implementa ‘mutable’, e você quer criar uma class que seja logicamente const mas não bitwise const. Você pode const_cast ‘this’ dentro de um método const e modificar membros de sua class.

 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(this); update_cache(thisptr->cached_data); } return cached_data[index]; } }; 

Acho difícil acreditar que essa é a única informação que você pode encontrar sobre const_cast. Citando o segundo hit do Google :

Se você ignorar a constância de um object declarado explicitamente como const e tentar modificá-lo, os resultados serão indefinidos.

No entanto, se você ignorar a constância de um object que não foi explicitamente declarado como const, poderá modificá-lo com segurança.

O que Adam diz? Outro exemplo em que const_cast pode ser útil:

 struct sample { T& getT() { return const_cast(static_cast(this)->getT()); } const T& getT() const { /* possibly much code here */ return t; } T t; }; 

Primeiro adicionamos const ao tipo para o qual this aponta, então chamamos a versão const de getT e então removemos const do tipo de retorno, que é válido, pois t deve ser non-const (caso contrário, a versão não-const de getT não poderia ter sido chamado). Isso pode ser muito útil se você tiver um corpo de function grande e quiser evitar código redundante.

A resposta curta é não, não é seguro.

A resposta longa é que, se você souber o suficiente para usá-la, ela deve ser segura.

Quando você está lançando, o que você está essencialmente dizendo é: “Eu sei de algo que o compilador não sabe”. No caso do const_cast, o que você está dizendo é: “Mesmo que este método tenha uma referência ou ponteiro não-constante, eu sei que isso não mudará o parâmetro que eu passo.”

Então, se você realmente sabe o que está afirmando saber sobre o uso do casting, não há problema em usá-lo.

Você está destruindo qualquer chance de segurança de thread, se você começar a modificar coisas que o compilador pensou que eram constantes.

 #include  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(b); f(c); // Lvalue is const // *b = 20; // Undefined behavior // *c = 30; int a1 = 40; const int* b1 = &a1; int* c1 = const_cast(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