C ++ const cast, não tem certeza se isso é seguro

Talvez pareça ser uma pergunta boba, mas eu realmente preciso esclarecer isso:

Isso trará algum perigo para o meu programa?

O const_cast é necessário?

Se eu alterar os valores dos pointers de input no local, ele funcionará com segurança com std::string ou criará um comportamento indefinido?

Até agora, a única preocupação é que isso possa afetar a string “some_text” sempre que eu modifico o ponteiro de input e o inutilizo.

 std::string some_text = "Text with some input"; char * input = const_cast(some_text.c_str()); 

Obrigado por me dar algumas dicas, eu gostaria de evitar a filmagem no meu próprio pé

Como um exemplo de mau comportamento: a interação com a implementação Copy On Write do gcc.

 #include  #include  int main() { std::string const original = "Hello, World!"; std::string copy = original; char* c = const_cast(copy.c_str()); c[0] = 'J'; std::cout << original << "\n"; } 

Em ação no ideone .

Gelatina, mundo!

O problema ? Como o nome indica, a implementação do std::string do gcc usa um buffer compartilhado contado na tampa. Quando uma string é modificada, a implementação verificará se o buffer está compartilhado no momento e, se estiver, copie-o antes de modificá-lo, garantindo que outras strings que compartilham esse buffer não sejam afetadas pela nova gravação (daí o nome, cópia na gravação).

Agora, com seu programa maligno, você acessa o buffer compartilhado através de um método const (prometendo não modificar nada), mas você o modifica!

Observe que com a implementação do MSVC, que não usa Copy On Write, o comportamento seria diferente ( "Hello, World!" Seria corretamente impresso).

Esta é exatamente a essência do comportamento indefinido .

Para modificar um object const inerentemente ao lançar sua constância usando const_cast é um comportamento indefinido .

string :: c_str () retorna um const char * , ie: um ponteiro para uma string constante no estilo c. Tecnicamente, modificar isso resultará em Comportamento Indefinido.

Note que o uso de const_cast é quando você tem um ponteiro const para um dado non const e deseja modificar os dados não-constantes.

Simplesmente lançar não trará um comportamento indefinido. Modificando os dados apontados, no entanto, será. ( Veja também ISO 14882: 98 5.2.7-7 ).

Se você quiser um ponteiro para dados modificáveis, você pode ter um

 std::vector wtf(str.begin(), str.end()); char* lol= &wtf[0]; 

O std::string gerencia sua própria memory internamente, e é por isso que ele retorna um ponteiro para essa memory diretamente, como acontece com a function c_str() . Isso garante que seja constante para que seu compilador o avise caso tente modificá-lo.

Usar o const_cast dessa forma literalmente elimina essa segurança e é apenas uma prática discutivelmente aceitável se você estiver absolutamente certo de que a memory não será modificada.

Se você não pode garantir isso, então você deve copiar a string e usar a cópia; certamente é muito mais seguro fazer isso em qualquer evento (você pode usar o strcpy ).

Veja o site de referência C ++ :

 const char* c_str ( ) const; 

“Gera uma seqüência de caracteres terminada com nulo (string C) com o mesmo conteúdo que o object string e a retorna como um ponteiro para uma matriz de caracteres.

Um caractere nulo de terminação é automaticamente anexado.

A matriz retornada aponta para um local interno com o espaço de armazenamento necessário para essa seqüência de caracteres mais seu caractere nulo de terminação, mas os valores nessa matriz não devem ser modificados no programa e só terão a garantia de permanecer inalterados até a próxima chamada a uma function de membro não constante do object string. ”

Sim, isso trará perigo, porque

  1. pontos de input para qualquer c_str aconteça ser agora, mas se some_text nunca muda ou desaparece, você vai ficar com um ponteiro que aponta para o lixo. O valor de c_str é garantido como válido apenas enquanto a string não for alterada. E mesmo, formalmente, somente se você não chamar c_str() em outras strings também.
  2. Por que você precisa jogar fora o const? Você não está planejando escrever para *input , está? Isso é um não-não!

Isso é uma coisa muito ruim de se fazer. Confira o que std :: string :: c_str () faz e concorda comigo.

Em segundo lugar, considere por que você deseja um access não-constante aos internos da std :: string. Aparentemente, você quer modificar o conteúdo, porque senão você usaria um ponteiro const char. Você também está preocupado que não queira alterar a string original. Por que não escrever

 std::string input( some_text ); 

Então você tem um std :: string que você pode mexer sem afetar o original, e você tem a funcionalidade std :: string em vez de ter que trabalhar com um ponteiro C ++ bruto …

Outro giro sobre isso é que torna o código extremamente difícil de manter. Caso em questão: há alguns anos tive que refatorar algum código contendo funções longas. O autor tinha escrito as assinaturas de function para aceitar parâmetros constantes, mas depois foi const_cast -los dentro da function para remover a constância. Isso quebrou a garantia implícita dada pela function e tornou muito difícil saber se o parâmetro foi alterado ou não dentro do resto do corpo do código.

Em suma, se você tiver controle sobre a string e achar que precisará alterá-la, torne-a não-const em primeiro lugar. Se você não fizer isso, você terá que pegar uma cópia e trabalhar com isso.

é o UB. Por exemplo, você pode fazer algo assim:

 size_t const size = (sizeof(int) == 4 ? 1024 : 2048); int arr[size]; 

sem qualquer conversão e o comutador não reportará um erro. Mas esse código é ilegal. A moral é que você precisa considerar a ação a cada vez.