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?

Foi útil?

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.

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