Alterando dados ignorando o qualificador const
Pergunta
Eu fiz uma pergunta relacionada anteriormente sobre isso, então sei que é um comportamento indefinido.
retornando const char* para char* e depois alterando os dados
string _str = "SDFDFSD";
char* pStr = (char*)_str.data();
for (int i = 0; i < iSize; i++)
pStr[i] = ::tolower(pStr[i]);
Tive uma discussão com um dos meus colegas sobre isso.E ele me disse que isso não causará nenhum problema nesse cenário, a menos que eu altere o comprimento dos dados.Se eu alterar os dados, mas mantiver o comprimento igual, isso nunca criará nenhum problema, pois não há como std::string
para detectar que os dados foram alterados.Também não causará nenhuma inconsistência interna _str
.É realmente o caso?
Solução
Comportamento indefinido temo que tenha sido muito criticado, e as referências a demônios nasais parecem ter convencido a maioria das pessoas de que era mais mítico do que qualquer outra coisa.
Parece que o seu colega ficou tão insensível que, para convencê-lo, é necessário trazer-lhe provas concretas do assunto.Felizmente, se você tiver o gcc em mãos, isso pode ser feito:
#include <iostream>
#include <string>
int main() {
std::string const UPPER = "HELLO, WORLD!";
std::cout << "UPPER: " << UPPER << "\n";
std::string lower = UPPER;
for (char* begin = const_cast<char*>(lower.data()),
* end = begin + lower.size();
begin != end;
++begin)
{
*begin = std::tolower(*begin);
}
std::cout << "lower: " << lower << "\n";
std::cout << "UPPER: " << UPPER << "\n";
return 0;
}
Se você usa gcc, aqui está o que você ganha:
UPPER: HELLO, WORLD!
lower: hello, world!
UPPER: hello, world! // What the hell ? UPPER was const !!!
Por que ?Como o gcc historicamente usou Copiar na gravação, e já que você enganado ele não detectou a gravação e, portanto, a matriz de armazenamento subjacente é compartilhada.
Observação:sim, isso não está em conformidade com C++ 11, mas gostaria de ter a chance de trabalhar em C++ 11.
Outras dicas
Conforme dados() documentação:
Modificar a matriz de caracteres acessada por meio de dados é um comportamento indefinido.
Então seu colega está errado, não tem truque, é um comportamento indefinido.O que acontece é específico da implementação.
Péssima ideia!Você não pode saber com certeza como a string é implementada em qualquer plataforma atual ou futura.Por exemplo, poderia ser o compartilhamento de armazenamento com outros objetos que sejam de alguma forma semelhantes.Poderia ser colocar os dados em um segmento somente leitura em algumas plataformas.