Pergunta

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

O const_cast<>() é usado para adicionar / const remove (ness) (ou volátil-ness) de uma variável.

Isto faz-me nervoso. Poderia utilizar um const_cast causar um comportamento inesperado? Se sim, qual? ??

Como alternativa, quando está tudo bem para uso const_cast?

Foi útil?

Solução

const_cast é seguro somente se você está lançando uma variável que foi originalmente não const. Por exemplo, se você tem uma função que leva um parâmetro de uma const char *, e você passar em um char * modificável, é seguro const_cast que o parâmetro de volta para um char * e modificá-lo. No entanto, se a variável original era de fato const, em seguida, usando const_cast irá resultar em um comportamento indefinido.

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

Outras dicas

Não consigo pensar em duas situações onde const_cast é seguro e útil (pode haver outros casos válidos).

Uma delas é quando você tem uma instância const, referência, ou ponteiro, e você quer passar um ponteiro ou referência a uma API que não é const-correto, mas que você está certo vontade não modificar o objeto. 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<char*>(&message.c_str()));
}

O outro é se você estiver usando um compilador mais antigo que não implementa 'mutável', e você quer criar uma classe que é logicamente const, mas não const bit a bit. Você pode const_cast 'this' dentro de um método const e modificar os membros de sua 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];
    }
};

Acho que é difícil acreditar que essa é a única informação que pude encontrar sobre const_cast. Citando o segunda Google atingiu :

Se você jogar fora o constness de um objeto que tenha sido explicitamente declarada como const, e tentar modificá-lo, os resultados são indefinido.

No entanto, se você jogar fora o constness de um objecto que não possui foi explicitamente declarado como const, você pode modificá-lo com segurança.

O que diz Adam. Outro exemplo onde const_cast pode ser útil:

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

Em primeiro lugar, adicionar const para o tipo this aponta para, em seguida, chamamos a versão const de getT, e então remover const do tipo de retorno, que é válido desde t deve ser não-const (caso contrário, o não-const versão do getT não poderia ter sido chamado). Isto pode ser muito útil se você tem um grande corpo da função e você quer evitar código redundante.

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

A resposta longa é que, se você sabe o suficiente para usá-lo, então ele deve ser seguro.

Quando você está casting, o que você está basicamente dizendo é: "Eu sei algo que o compilador não sabe." No caso de const_cast, o que você está dizendo é: "Mesmo que este método leva em uma referência não-const ou ponteiro, eu sei que não vai alterar o parâmetro que passá-lo."

Então, se você realmente sabe o que está dizendo saber em usar o elenco, então não há problema em usá-lo.

Você está destruindo qualquer chance de thread-segurança, se você começar coisas modificando que o pensamento compilador eram 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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top