Domanda

Ho già posto una domanda correlata a questo proposito, quindi so che si tratta di un comportamento indefinito.

restituendo const char* a char* e quindi modificando i dati

string _str = "SDFDFSD";
char* pStr = (char*)_str.data();
for (int i = 0; i < iSize; i++)
    pStr[i] = ::tolower(pStr[i]);

Ho discusso di questo con uno dei miei colleghi.E mi ha detto che non causerà mai alcun problema in questo scenario a meno che non modifichi la lunghezza dei dati.Se cambio i dati ma mantengo la stessa lunghezza, non creerò mai alcun problema poiché non c'è modo di farlo std::string per rilevare che i dati sono stati modificati.Non causerà alcuna incoerenza interna neanche nel _str.È davvero così?

È stato utile?

Soluzione

Comportamento indefinito è stato denigrato troppo, temo, e i riferimenti ai demoni nasali sembrano aver convinto la maggior parte delle persone che fosse più mitico di ogni altra cosa.

Sembra che il tuo collega sia stato così desensibilizzato che per convincerti è necessario portargli prove concrete del problema.Fortunatamente, se hai gcc a portata di mano, puoi farlo:

#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 usi gcc, ecco cosa ottieni:

UPPER: HELLO, WORLD!
lower: hello, world!
UPPER: hello, world!   // What the hell ? UPPER was const !!!

Perché ?Perché gcc ha storicamente utilizzato Copia su scrittura, e poiché tu imbrogliato non ha rilevato la scrittura e quindi l'array di archiviazione sottostante è condiviso.

Nota:sì, questo non è conforme a C++11, vorrei però avere la possibilità di lavorare in C++11.

Altri suggerimenti

Secondo il dati() documentazione:

La modifica dell'array di caratteri a cui si accede tramite i dati è un comportamento indefinito.

Quindi il tuo collega ha torto, non c'è nessun trucco, è un comportamento indefinito.Ciò che accade è specifico dell'implementazione.

Cattiva idea!Non puoi sapere con certezza come viene implementata la stringa su qualsiasi piattaforma attuale o futura.Ad esempio, potrebbe condividere lo spazio di archiviazione con altri oggetti in qualche modo simili.Potrebbe inserire i dati in un segmento di sola lettura su alcune piattaforme.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top